Auto merge of #57869 - Centril:rollup, r=Centril

Rollup of 11 pull requests

Successful merges:

 - #57179 (Update std/lib.rs docs to reflect Rust 2018 usage)
 - #57730 (Merge visitors in AST validation)
 - #57779 (Recover from parse errors in literal struct fields and incorrect float literals)
 - #57793 (Explain type mismatch cause pointing to return type when it is `impl Trait`)
 - #57795 (Use structured suggestion in stead of notes)
 - #57817 (Add error for trailing angle brackets.)
 - #57834 (Stabilize Any::get_type_id and rename to type_id)
 - #57836 (Fix some cross crate existential type ICEs)
 - #57840 (Fix issue 57762)
 - #57844 (use port 80 for retrieving GPG key)
 - #57858 (Ignore line ending on older git versions)

Failed merges:

r? @ghost
This commit is contained in:
bors 2019-01-24 01:24:13 +00:00
commit cd3d580d59
47 changed files with 840 additions and 310 deletions

4
.gitattributes vendored
View File

@ -9,3 +9,7 @@ src/etc/installer/gfx/* binary
*.woff binary
src/vendor/** -text
Cargo.lock -merge linguist-generated=false
# Older git versions try to fix line endings on images, this prevents it.
*.png binary
*.ico binary

View File

@ -6,7 +6,7 @@ set -ex
apt-get update
apt-get install -y --no-install-recommends software-properties-common apt-transport-https
apt-key adv --batch --yes --keyserver keyserver.ubuntu.com --recv-keys AA12E97F0881517F
apt-key adv --batch --yes --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys AA12E97F0881517F
add-apt-repository -y 'deb https://static.redox-os.org/toolchain/apt /'
apt-get update

View File

@ -81,12 +81,10 @@ pub trait Any: 'static {
/// # Examples
///
/// ```
/// #![feature(get_type_id)]
///
/// use std::any::{Any, TypeId};
///
/// fn is_string(s: &dyn Any) -> bool {
/// TypeId::of::<String>() == s.get_type_id()
/// TypeId::of::<String>() == s.type_id()
/// }
///
/// fn main() {
@ -94,15 +92,13 @@ pub trait Any: 'static {
/// assert_eq!(is_string(&"cookie monster".to_string()), true);
/// }
/// ```
#[unstable(feature = "get_type_id",
reason = "this method will likely be replaced by an associated static",
issue = "27745")]
fn get_type_id(&self) -> TypeId;
#[stable(feature = "get_type_id", since = "1.34.0")]
fn type_id(&self) -> TypeId;
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: 'static + ?Sized > Any for T {
fn get_type_id(&self) -> TypeId { TypeId::of::<T>() }
fn type_id(&self) -> TypeId { TypeId::of::<T>() }
}
///////////////////////////////////////////////////////////////////////////////
@ -161,10 +157,10 @@ impl dyn Any {
let t = TypeId::of::<T>();
// Get TypeId of the type in the trait object
let boxed = self.get_type_id();
let concrete = self.type_id();
// Compare both TypeIds on equality
t == boxed
t == concrete
}
/// Returns some reference to the boxed value if it is of type `T`, or

View File

@ -1164,7 +1164,10 @@ fn use_enum_fallback(cx: &CodegenCx) -> bool {
// On MSVC we have to use the fallback mode, because LLVM doesn't
// lower variant parts to PDB.
return cx.sess().target.target.options.is_like_msvc
|| llvm_util::get_major_version() < 7;
// LLVM version 7 did not release with an important bug fix;
// but the required patch is in the LLVM 8. Rust LLVM reports
// 8 as well.
|| llvm_util::get_major_version() < 8;
}
// Describes the members of an enum value: An enum is described as a union of

View File

@ -893,6 +893,9 @@ impl<'a, 'tcx> CrateMetadata {
EntryKind::AssociatedType(container) => {
(ty::AssociatedKind::Type, container, false)
}
EntryKind::AssociatedExistential(container) => {
(ty::AssociatedKind::Existential, container, false)
}
_ => bug!("cannot get associated-item of `{:?}`", def_key)
};

View File

@ -6,6 +6,7 @@
// This pass is supposed to perform only simple checks not requiring name resolution
// or type checking or some other kind of complex analysis.
use std::mem;
use rustc::lint;
use rustc::session::Session;
use syntax::ast::*;
@ -20,9 +21,73 @@ use errors::Applicability;
struct AstValidator<'a> {
session: &'a Session,
// Used to ban nested `impl Trait`, e.g., `impl Into<impl Debug>`.
// Nested `impl Trait` _is_ allowed in associated type position,
// e.g `impl Iterator<Item=impl Debug>`
outer_impl_trait: Option<Span>,
// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
// or `Foo::Bar<impl Trait>`
is_impl_trait_banned: bool,
}
impl<'a> AstValidator<'a> {
fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
let old = mem::replace(&mut self.is_impl_trait_banned, true);
f(self);
self.is_impl_trait_banned = old;
}
fn with_impl_trait(&mut self, outer_impl_trait: Option<Span>, f: impl FnOnce(&mut Self)) {
let old = mem::replace(&mut self.outer_impl_trait, outer_impl_trait);
f(self);
self.outer_impl_trait = old;
}
// Mirrors visit::walk_ty, but tracks relevant state
fn walk_ty(&mut self, t: &'a Ty) {
match t.node {
TyKind::ImplTrait(..) => {
self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t))
}
TyKind::Path(ref qself, ref path) => {
// We allow these:
// - `Option<impl Trait>`
// - `option::Option<impl Trait>`
// - `option::Option<T>::Foo<impl Trait>
//
// But not these:
// - `<impl Trait>::Foo`
// - `option::Option<impl Trait>::Foo`.
//
// To implement this, we disallow `impl Trait` from `qself`
// (for cases like `<impl Trait>::Foo>`)
// but we allow `impl Trait` in `GenericArgs`
// iff there are no more PathSegments.
if let Some(ref qself) = *qself {
// `impl Trait` in `qself` is always illegal
self.with_banned_impl_trait(|this| this.visit_ty(&qself.ty));
}
// Note that there should be a call to visit_path here,
// so if any logic is added to process `Path`s a call to it should be
// added both in visit_path and here. This code mirrors visit::walk_path.
for (i, segment) in path.segments.iter().enumerate() {
// Allow `impl Trait` iff we're on the final path segment
if i == path.segments.len() - 1 {
self.visit_path_segment(path.span, segment);
} else {
self.with_banned_impl_trait(|this| {
this.visit_path_segment(path.span, segment)
});
}
}
}
_ => visit::walk_ty(self, t),
}
}
fn err_handler(&self) -> &errors::Handler {
&self.session.diagnostic()
}
@ -267,6 +332,19 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.no_questions_in_bounds(bounds, "trait object types", false);
}
TyKind::ImplTrait(_, ref bounds) => {
if self.is_impl_trait_banned {
struct_span_err!(self.session, ty.span, E0667,
"`impl Trait` is not allowed in path parameters").emit();
}
if let Some(outer_impl_trait) = self.outer_impl_trait {
struct_span_err!(self.session, ty.span, E0666,
"nested `impl Trait` is not allowed")
.span_label(outer_impl_trait, "outer `impl Trait`")
.span_label(ty.span, "nested `impl Trait` here")
.emit();
}
if !bounds.iter()
.any(|b| if let GenericBound::Trait(..) = *b { true } else { false }) {
self.err_handler().span_err(ty.span, "at least one trait must be specified");
@ -275,7 +353,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
_ => {}
}
visit::walk_ty(self, ty)
self.walk_ty(ty)
}
fn visit_label(&mut self, label: &'a Label) {
@ -414,6 +492,28 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
visit::walk_foreign_item(self, fi)
}
// Mirrors visit::walk_generic_args, but tracks relevant state
fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
match *generic_args {
GenericArgs::AngleBracketed(ref data) => {
walk_list!(self, visit_generic_arg, &data.args);
// Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
// are allowed to contain nested `impl Trait`.
self.with_impl_trait(None, |this| {
walk_list!(this, visit_assoc_type_binding, &data.bindings);
});
}
GenericArgs::Parenthesized(ref data) => {
walk_list!(self, visit_ty, &data.inputs);
if let Some(ref type_) = data.output {
// `-> Foo` syntax is essentially an associated type binding,
// so it is also allowed to contain nested `impl Trait`.
self.with_impl_trait(None, |this| visit::walk_ty(this, type_));
}
}
}
}
fn visit_generics(&mut self, generics: &'a Generics) {
let mut seen_non_lifetime_param = false;
let mut seen_default = None;
@ -490,148 +590,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
}
// Bans nested `impl Trait`, e.g., `impl Into<impl Debug>`.
// Nested `impl Trait` _is_ allowed in associated type position,
// e.g `impl Iterator<Item=impl Debug>`
struct NestedImplTraitVisitor<'a> {
session: &'a Session,
outer_impl_trait: Option<Span>,
}
impl<'a> NestedImplTraitVisitor<'a> {
fn with_impl_trait<F>(&mut self, outer_impl_trait: Option<Span>, f: F)
where F: FnOnce(&mut NestedImplTraitVisitor<'a>)
{
let old_outer_impl_trait = self.outer_impl_trait;
self.outer_impl_trait = outer_impl_trait;
f(self);
self.outer_impl_trait = old_outer_impl_trait;
}
}
impl<'a> Visitor<'a> for NestedImplTraitVisitor<'a> {
fn visit_ty(&mut self, t: &'a Ty) {
if let TyKind::ImplTrait(..) = t.node {
if let Some(outer_impl_trait) = self.outer_impl_trait {
struct_span_err!(self.session, t.span, E0666,
"nested `impl Trait` is not allowed")
.span_label(outer_impl_trait, "outer `impl Trait`")
.span_label(t.span, "nested `impl Trait` here")
.emit();
}
self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t));
} else {
visit::walk_ty(self, t);
}
}
fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
match *generic_args {
GenericArgs::AngleBracketed(ref data) => {
for arg in &data.args {
self.visit_generic_arg(arg)
}
for type_binding in &data.bindings {
// Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
// are allowed to contain nested `impl Trait`.
self.with_impl_trait(None, |this| visit::walk_ty(this, &type_binding.ty));
}
}
GenericArgs::Parenthesized(ref data) => {
for type_ in &data.inputs {
self.visit_ty(type_);
}
if let Some(ref type_) = data.output {
// `-> Foo` syntax is essentially an associated type binding,
// so it is also allowed to contain nested `impl Trait`.
self.with_impl_trait(None, |this| visit::walk_ty(this, type_));
}
}
}
}
fn visit_mac(&mut self, _mac: &Spanned<Mac_>) {
// covered in AstValidator
}
}
// Bans `impl Trait` in path projections like `<impl Iterator>::Item` or `Foo::Bar<impl Trait>`.
struct ImplTraitProjectionVisitor<'a> {
session: &'a Session,
is_banned: bool,
}
impl<'a> ImplTraitProjectionVisitor<'a> {
fn with_ban<F>(&mut self, f: F)
where F: FnOnce(&mut ImplTraitProjectionVisitor<'a>)
{
let old_is_banned = self.is_banned;
self.is_banned = true;
f(self);
self.is_banned = old_is_banned;
}
}
impl<'a> Visitor<'a> for ImplTraitProjectionVisitor<'a> {
fn visit_ty(&mut self, t: &'a Ty) {
match t.node {
TyKind::ImplTrait(..) => {
if self.is_banned {
struct_span_err!(self.session, t.span, E0667,
"`impl Trait` is not allowed in path parameters").emit();
}
}
TyKind::Path(ref qself, ref path) => {
// We allow these:
// - `Option<impl Trait>`
// - `option::Option<impl Trait>`
// - `option::Option<T>::Foo<impl Trait>
//
// But not these:
// - `<impl Trait>::Foo`
// - `option::Option<impl Trait>::Foo`.
//
// To implement this, we disallow `impl Trait` from `qself`
// (for cases like `<impl Trait>::Foo>`)
// but we allow `impl Trait` in `GenericArgs`
// iff there are no more PathSegments.
if let Some(ref qself) = *qself {
// `impl Trait` in `qself` is always illegal
self.with_ban(|this| this.visit_ty(&qself.ty));
}
for (i, segment) in path.segments.iter().enumerate() {
// Allow `impl Trait` iff we're on the final path segment
if i == path.segments.len() - 1 {
visit::walk_path_segment(self, path.span, segment);
} else {
self.with_ban(|this|
visit::walk_path_segment(this, path.span, segment));
}
}
}
_ => visit::walk_ty(self, t),
}
}
fn visit_mac(&mut self, _mac: &Spanned<Mac_>) {
// covered in AstValidator
}
}
pub fn check_crate(session: &Session, krate: &Crate) {
visit::walk_crate(
&mut NestedImplTraitVisitor {
session,
outer_impl_trait: None,
}, krate);
visit::walk_crate(
&mut ImplTraitProjectionVisitor {
session,
is_banned: false,
}, krate);
visit::walk_crate(&mut AstValidator { session }, krate)
visit::walk_crate(&mut AstValidator {
session,
outer_impl_trait: None,
is_impl_trait_banned: false,
}, krate)
}

View File

@ -680,6 +680,7 @@ impl<'a> Resolver<'a> {
}
module.populated.set(true);
}
Def::Existential(..) |
Def::TraitAlias(..) => {
self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
}

View File

@ -1199,7 +1199,6 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
(self.final_ty.unwrap_or(self.expected_ty), expression_ty)
};
let reason_label = "expected because of this statement";
let mut db;
match cause.code {
ObligationCauseCode::ReturnNoExpression => {
@ -1209,63 +1208,20 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
db.span_label(cause.span, "return type is not `()`");
}
ObligationCauseCode::BlockTailExpression(blk_id) => {
db = fcx.report_mismatched_types(cause, expected, found, err);
let expr = expression.unwrap_or_else(|| {
span_bug!(cause.span,
"supposed to be part of a block tail expression, but the \
expression is empty");
});
let pointing_at_return_type = fcx.suggest_mismatched_types_on_tail(
&mut db,
expr,
let parent_id = fcx.tcx.hir().get_parent_node(blk_id);
db = self.report_return_mismatched_types(
cause,
expected,
found,
cause.span,
blk_id,
err,
fcx,
parent_id,
expression.map(|expr| (expr, blk_id)),
);
// FIXME: replace with navigating up the chain until hitting an fn or
// bailing if no "pass-through" Node is found, in order to provide a
// suggestion when encountering something like:
// ```
// fn foo(a: bool) -> impl Debug {
// if a {
// bar()?;
// }
// {
// let x = unsafe { bar() };
// x
// }
// }
// ```
//
// Verify that this is a tail expression of a function, otherwise the
// label pointing out the cause for the type coercion will be wrong
// as prior return coercions would not be relevant (#57664).
let parent_id = fcx.tcx.hir().get_parent_node(blk_id);
let parent = fcx.tcx.hir().get(fcx.tcx.hir().get_parent_node(parent_id));
if fcx.get_node_fn_decl(parent).is_some() && !pointing_at_return_type {
if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() {
db.span_label(*sp, reason_label);
}
}
}
ObligationCauseCode::ReturnType(_id) => {
db = fcx.report_mismatched_types(cause, expected, found, err);
let _id = fcx.tcx.hir().get_parent_node(_id);
let mut pointing_at_return_type = false;
if let Some((fn_decl, can_suggest)) = fcx.get_fn_decl(_id) {
pointing_at_return_type = fcx.suggest_missing_return_type(
&mut db, &fn_decl, expected, found, can_suggest);
}
if let (Some(sp), false) = (
fcx.ret_coercion_span.borrow().as_ref(),
pointing_at_return_type,
) {
if !sp.overlaps(cause.span) {
db.span_label(*sp, reason_label);
}
}
ObligationCauseCode::ReturnType(id) => {
db = self.report_return_mismatched_types(
cause, expected, found, err, fcx, id, None);
}
_ => {
db = fcx.report_mismatched_types(cause, expected, found, err);
@ -1283,6 +1239,59 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
}
}
fn report_return_mismatched_types<'a>(
&self,
cause: &ObligationCause<'tcx>,
expected: Ty<'tcx>,
found: Ty<'tcx>,
err: TypeError<'tcx>,
fcx: &FnCtxt<'a, 'gcx, 'tcx>,
id: syntax::ast::NodeId,
expression: Option<(&'gcx hir::Expr, syntax::ast::NodeId)>,
) -> DiagnosticBuilder<'a> {
let mut db = fcx.report_mismatched_types(cause, expected, found, err);
let mut pointing_at_return_type = false;
let mut return_sp = None;
// Verify that this is a tail expression of a function, otherwise the
// label pointing out the cause for the type coercion will be wrong
// as prior return coercions would not be relevant (#57664).
let parent_id = fcx.tcx.hir().get_parent_node(id);
let fn_decl = if let Some((expr, blk_id)) = expression {
pointing_at_return_type = fcx.suggest_mismatched_types_on_tail(
&mut db,
expr,
expected,
found,
cause.span,
blk_id,
);
let parent = fcx.tcx.hir().get(parent_id);
fcx.get_node_fn_decl(parent).map(|(fn_decl, _, is_main)| (fn_decl, is_main))
} else {
fcx.get_fn_decl(parent_id)
};
if let (Some((fn_decl, can_suggest)), _) = (fn_decl, pointing_at_return_type) {
if expression.is_none() {
pointing_at_return_type |= fcx.suggest_missing_return_type(
&mut db, &fn_decl, expected, found, can_suggest);
}
if !pointing_at_return_type {
return_sp = Some(fn_decl.output.span()); // `impl Trait` return type
}
}
if let (Some(sp), Some(return_sp)) = (fcx.ret_coercion_span.borrow().as_ref(), return_sp) {
db.span_label(return_sp, "expected because this return type...");
db.span_label( *sp, format!(
"...is found to be `{}` here",
fcx.resolve_type_vars_with_obligations(expected),
));
}
db
}
pub fn complete<'a>(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
if let Some(final_ty) = self.final_ty {
final_ty

View File

@ -304,7 +304,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
);
if let Some(suggestion) = suggestion {
// enum variant
err.help(&format!("did you mean `{}`?", suggestion));
err.span_suggestion_with_applicability(
item_name.span,
"did you mean",
suggestion.to_string(),
Applicability::MaybeIncorrect,
);
}
err
}
@ -440,7 +445,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
if let Some(lev_candidate) = lev_candidate {
err.help(&format!("did you mean `{}`?", lev_candidate.ident));
err.span_suggestion_with_applicability(
span,
"did you mean",
lev_candidate.ident.to_string(),
Applicability::MaybeIncorrect,
);
}
err.emit();
}

View File

@ -608,8 +608,8 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
if let ty::Opaque(def_id, substs) = ty.sty {
trace!("check_existential_types: opaque_ty, {:?}, {:?}", def_id, substs);
let generics = tcx.generics_of(def_id);
// only check named existential types
if generics.parent.is_none() {
// only check named existential types defined in this crate
if generics.parent.is_none() && def_id.is_local() {
let opaque_node_id = tcx.hir().as_local_node_id(def_id).unwrap();
if may_define_existential_type(tcx, fn_def_id, opaque_node_id) {
trace!("check_existential_types may define. Generics: {:#?}", generics);

View File

@ -7,11 +7,9 @@
//! primitives](#primitives), [standard macros](#macros), [I/O] and
//! [multithreading], among [many other things][other].
//!
//! `std` is available to all Rust crates by default, just as if each one
//! contained an `extern crate std;` import at the [crate root]. Therefore the
//! `std` is available to all Rust crates by default. Therefore the
//! standard library can be accessed in [`use`] statements through the path
//! `std`, as in [`use std::env`], or in expressions through the absolute path
//! `::std`, as in [`::std::env::args`].
//! `std`, as in [`use std::env`].
//!
//! # How to read this documentation
//!
@ -157,7 +155,6 @@
//! [TCP]: net/struct.TcpStream.html
//! [The Rust Prelude]: prelude/index.html
//! [UDP]: net/struct.UdpSocket.html
//! [`::std::env::args`]: env/fn.args.html
//! [`Arc`]: sync/struct.Arc.html
//! [owned slice]: boxed/index.html
//! [`Cell`]: cell/struct.Cell.html
@ -191,7 +188,6 @@
//! [`thread`]: thread/index.html
//! [`use std::env`]: env/index.html
//! [`use`]: ../book/ch07-02-modules-and-use-to-control-scope-and-privacy.html#the-use-keyword-to-bring-paths-into-a-scope
//! [crate root]: ../book/ch07-01-packages-and-crates-for-making-libraries-and-executables.html
//! [crates.io]: https://crates.io
//! [deref-coercions]: ../book/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods
//! [files]: fs/struct.File.html

View File

@ -140,6 +140,20 @@ pub enum GenericArgs {
}
impl GenericArgs {
pub fn is_parenthesized(&self) -> bool {
match *self {
Parenthesized(..) => true,
_ => false,
}
}
pub fn is_angle_bracketed(&self) -> bool {
match *self {
AngleBracketed(..) => true,
_ => false,
}
}
pub fn span(&self) -> Span {
match *self {
AngleBracketed(ref data) => data.span,

View File

@ -100,6 +100,7 @@ pub enum PathStyle {
enum SemiColonMode {
Break,
Ignore,
Comma,
}
#[derive(Clone, Copy, PartialEq, Debug)]
@ -1988,6 +1989,44 @@ impl<'a> Parser<'a> {
result.unwrap()
}
token::Dot if self.look_ahead(1, |t| match t {
token::Literal(parse::token::Lit::Integer(_) , _) => true,
_ => false,
}) => { // recover from `let x = .4;`
let lo = self.span;
self.bump();
if let token::Literal(
parse::token::Lit::Integer(val),
suffix,
) = self.token {
let suffix = suffix.and_then(|s| {
let s = s.as_str().get();
if ["f32", "f64"].contains(&s) {
Some(s)
} else {
None
}
}).unwrap_or("");
self.bump();
let sp = lo.to(self.prev_span);
let mut err = self.diagnostic()
.struct_span_err(sp, "float literals must have an integer part");
err.span_suggestion_with_applicability(
sp,
"must have an integer part",
format!("0.{}{}", val, suffix),
Applicability::MachineApplicable,
);
err.emit();
return Ok(match suffix {
"f32" => ast::LitKind::Float(val, ast::FloatTy::F32),
"f64" => ast::LitKind::Float(val, ast::FloatTy::F64),
_ => ast::LitKind::FloatUnsuffixed(val),
});
} else {
unreachable!();
};
}
_ => { return self.unexpected_last(&self.token); }
};
@ -2149,7 +2188,27 @@ impl<'a> Parser<'a> {
enable_warning: bool)
-> PResult<'a, ()> {
loop {
segments.push(self.parse_path_segment(style, enable_warning)?);
let segment = self.parse_path_segment(style, enable_warning)?;
if style == PathStyle::Expr {
// In order to check for trailing angle brackets, we must have finished
// recursing (`parse_path_segment` can indirectly call this function),
// that is, the next token must be the highlighted part of the below example:
//
// `Foo::<Bar as Baz<T>>::Qux`
// ^ here
//
// As opposed to the below highlight (if we had only finished the first
// recursion):
//
// `Foo::<Bar as Baz<T>>::Qux`
// ^ here
//
// `PathStyle::Expr` is only provided at the root invocation and never in
// `parse_path_segment` to recurse and therefore can be checked to maintain
// this invariant.
self.check_trailing_angle_brackets(&segment, token::ModSep);
}
segments.push(segment);
if self.is_import_coupler() || !self.eat(&token::ModSep) {
return Ok(());
@ -2656,8 +2715,24 @@ impl<'a> Parser<'a> {
break;
}
let mut recovery_field = None;
if let token::Ident(ident, _) = self.token {
if !self.token.is_reserved_ident() && self.look_ahead(1, |t| *t == token::Colon) {
// Use in case of error after field-looking code: `S { foo: () with a }`
let mut ident = ident.clone();
ident.span = self.span;
recovery_field = Some(ast::Field {
ident,
span: self.span,
expr: self.mk_expr(self.span, ExprKind::Err, ThinVec::new()),
is_shorthand: false,
attrs: ThinVec::new(),
});
}
}
let mut parsed_field = None;
match self.parse_field() {
Ok(f) => fields.push(f),
Ok(f) => parsed_field = Some(f),
Err(mut e) => {
e.span_label(struct_sp, "while parsing this struct");
e.emit();
@ -2666,19 +2741,28 @@ impl<'a> Parser<'a> {
// what comes next as additional fields, rather than
// bailing out until next `}`.
if self.token != token::Comma {
self.recover_stmt();
break;
self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);
if self.token != token::Comma {
break;
}
}
}
}
match self.expect_one_of(&[token::Comma],
&[token::CloseDelim(token::Brace)]) {
Ok(()) => {}
Ok(()) => if let Some(f) = parsed_field.or(recovery_field) {
// only include the field if there's no parse error for the field name
fields.push(f);
}
Err(mut e) => {
if let Some(f) = recovery_field {
fields.push(f);
}
e.span_label(struct_sp, "while parsing this struct");
e.emit();
self.recover_stmt();
break;
self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);
self.eat(&token::Comma);
}
}
}
@ -2757,6 +2841,8 @@ impl<'a> Parser<'a> {
// Assuming we have just parsed `.`, continue parsing into an expression.
fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
let segment = self.parse_path_segment(PathStyle::Expr, true)?;
self.check_trailing_angle_brackets(&segment, token::OpenDelim(token::Paren));
Ok(match self.token {
token::OpenDelim(token::Paren) => {
// Method call `expr.f()`
@ -2784,6 +2870,116 @@ impl<'a> Parser<'a> {
})
}
/// This function checks if there are trailing angle brackets and produces
/// a diagnostic to suggest removing them.
///
/// ```ignore (diagnostic)
/// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
/// ^^ help: remove extra angle brackets
/// ```
fn check_trailing_angle_brackets(&mut self, segment: &PathSegment, end: token::Token) {
// This function is intended to be invoked after parsing a path segment where there are two
// cases:
//
// 1. A specific token is expected after the path segment.
// eg. `x.foo(`, `x.foo::<u32>(` (parenthesis - method call),
// `Foo::`, or `Foo::<Bar>::` (mod sep - continued path).
// 2. No specific token is expected after the path segment.
// eg. `x.foo` (field access)
//
// This function is called after parsing `.foo` and before parsing the token `end` (if
// present). This includes any angle bracket arguments, such as `.foo::<u32>` or
// `Foo::<Bar>`.
// We only care about trailing angle brackets if we previously parsed angle bracket
// arguments. This helps stop us incorrectly suggesting that extra angle brackets be
// removed in this case:
//
// `x.foo >> (3)` (where `x.foo` is a `u32` for example)
//
// This case is particularly tricky as we won't notice it just looking at the tokens -
// it will appear the same (in terms of upcoming tokens) as below (since the `::<u32>` will
// have already been parsed):
//
// `x.foo::<u32>>>(3)`
let parsed_angle_bracket_args = segment.args
.as_ref()
.map(|args| args.is_angle_bracketed())
.unwrap_or(false);
debug!(
"check_trailing_angle_brackets: parsed_angle_bracket_args={:?}",
parsed_angle_bracket_args,
);
if !parsed_angle_bracket_args {
return;
}
// Keep the span at the start so we can highlight the sequence of `>` characters to be
// removed.
let lo = self.span;
// We need to look-ahead to see if we have `>` characters without moving the cursor forward
// (since we might have the field access case and the characters we're eating are
// actual operators and not trailing characters - ie `x.foo >> 3`).
let mut position = 0;
// We can encounter `>` or `>>` tokens in any order, so we need to keep track of how
// many of each (so we can correctly pluralize our error messages) and continue to
// advance.
let mut number_of_shr = 0;
let mut number_of_gt = 0;
while self.look_ahead(position, |t| {
trace!("check_trailing_angle_brackets: t={:?}", t);
if *t == token::BinOp(token::BinOpToken::Shr) {
number_of_shr += 1;
true
} else if *t == token::Gt {
number_of_gt += 1;
true
} else {
false
}
}) {
position += 1;
}
// If we didn't find any trailing `>` characters, then we have nothing to error about.
debug!(
"check_trailing_angle_brackets: number_of_gt={:?} number_of_shr={:?}",
number_of_gt, number_of_shr,
);
if number_of_gt < 1 && number_of_shr < 1 {
return;
}
// Finally, double check that we have our end token as otherwise this is the
// second case.
if self.look_ahead(position, |t| {
trace!("check_trailing_angle_brackets: t={:?}", t);
*t == end
}) {
// Eat from where we started until the end token so that parsing can continue
// as if we didn't have those extra angle brackets.
self.eat_to_tokens(&[&end]);
let span = lo.until(self.span);
let plural = number_of_gt > 1 || number_of_shr >= 1;
self.diagnostic()
.struct_span_err(
span,
&format!("unmatched angle bracket{}", if plural { "s" } else { "" }),
)
.span_suggestion_with_applicability(
span,
&format!("remove extra angle bracket{}", if plural { "s" } else { "" }),
String::new(),
Applicability::MachineApplicable,
)
.emit();
}
}
fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
let mut e = e0;
let mut hi;
@ -4542,13 +4738,13 @@ impl<'a> Parser<'a> {
token::CloseDelim(token::DelimToken::Brace) => {
if brace_depth == 0 {
debug!("recover_stmt_ return - close delim {:?}", self.token);
return;
break;
}
brace_depth -= 1;
self.bump();
if in_block && bracket_depth == 0 && brace_depth == 0 {
debug!("recover_stmt_ return - block end {:?}", self.token);
return;
break;
}
}
token::CloseDelim(token::DelimToken::Bracket) => {
@ -4560,7 +4756,7 @@ impl<'a> Parser<'a> {
}
token::Eof => {
debug!("recover_stmt_ return - Eof");
return;
break;
}
token::Semi => {
self.bump();
@ -4568,7 +4764,17 @@ impl<'a> Parser<'a> {
brace_depth == 0 &&
bracket_depth == 0 {
debug!("recover_stmt_ return - Semi");
return;
break;
}
}
token::Comma => {
if break_on_semi == SemiColonMode::Comma &&
brace_depth == 0 &&
bracket_depth == 0 {
debug!("recover_stmt_ return - Semi");
break;
} else {
self.bump();
}
}
_ => {
@ -7275,9 +7481,16 @@ impl<'a> Parser<'a> {
// CONST ITEM
if self.eat_keyword(keywords::Mut) {
let prev_span = self.prev_span;
self.diagnostic().struct_span_err(prev_span, "const globals cannot be mutable")
.help("did you mean to declare a static?")
.emit();
let mut err = self.diagnostic()
.struct_span_err(prev_span, "const globals cannot be mutable");
err.span_label(prev_span, "cannot be mutable");
err.span_suggestion_with_applicability(
const_span,
"you might want to declare a static instead",
"static".to_owned(),
Applicability::MaybeIncorrect,
);
err.emit();
}
let (ident, item_, extra_attrs) = self.parse_item_const(None)?;
let prev_span = self.prev_span;

View File

@ -2,12 +2,11 @@ error[E0599]: no method named `test_mut` found for type `std::vec::Vec<{integer}
--> $DIR/auto-ref-slice-plus-ref.rs:7:7
|
LL | a.test_mut(); //~ ERROR no method named `test_mut` found
| ^^^^^^^^
| ^^^^^^^^ help: did you mean: `get_mut`
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `test_mut`, perhaps you need to implement it:
candidate #1: `MyIter`
= help: did you mean `get_mut`?
error[E0599]: no method named `test` found for type `std::vec::Vec<{integer}>` in the current scope
--> $DIR/auto-ref-slice-plus-ref.rs:8:7

View File

@ -2,9 +2,7 @@ error[E0599]: no method named `b` found for type `&Self` in the current scope
--> $DIR/issue-3563.rs:3:17
|
LL | || self.b()
| ^
|
= help: did you mean `a`?
| ^ help: did you mean: `a`
error: aborting due to previous error

View File

@ -51,20 +51,18 @@ error[E0599]: no variant named `Empty3` found for type `empty_struct::XE` in the
|
LL | let xe3 = XE::Empty3; //~ ERROR no variant named `Empty3` found for type
| ----^^^^^^
| |
| | |
| | help: did you mean: `XEmpty3`
| variant not found in `empty_struct::XE`
|
= help: did you mean `XEmpty3`?
error[E0599]: no variant named `Empty3` found for type `empty_struct::XE` in the current scope
--> $DIR/empty-struct-braces-expr.rs:23:19
|
LL | let xe3 = XE::Empty3(); //~ ERROR no variant named `Empty3` found for type
| ----^^^^^^
| |
| | |
| | help: did you mean: `XEmpty3`
| variant not found in `empty_struct::XE`
|
= help: did you mean `XEmpty3`?
error: aborting due to 8 previous errors

View File

@ -0,0 +1,12 @@
// Crate that exports an existential type. Used for testing cross-crate.
#![crate_type="rlib"]
#![feature(existential_type)]
pub existential type Foo: std::fmt::Debug;
pub fn foo() -> Foo {
5
}

View File

@ -0,0 +1,21 @@
// Crate that exports an existential type. Used for testing cross-crate.
#![crate_type="rlib"]
#![feature(existential_type)]
pub trait View {
type Tmp: Iterator<Item = u32>;
fn test(&self) -> Self::Tmp;
}
pub struct X;
impl View for X {
existential type Tmp: Iterator<Item = u32>;
fn test(&self) -> Self::Tmp {
vec![1,2,3].into_iter()
}
}

View File

@ -0,0 +1,16 @@
// aux-build:cross_crate_ice.rs
// compile-pass
extern crate cross_crate_ice;
struct Bar(cross_crate_ice::Foo);
impl Bar {
fn zero(&self) -> &cross_crate_ice::Foo {
&self.0
}
}
fn main() {
let _ = cross_crate_ice::foo();
}

View File

@ -0,0 +1,11 @@
// aux-build:cross_crate_ice2.rs
// compile-pass
extern crate cross_crate_ice2;
use cross_crate_ice2::View;
fn main() {
let v = cross_crate_ice2::X;
v.test();
}

View File

@ -1,8 +1,11 @@
error[E0308]: mismatched types
--> $DIR/equality.rs:15:5
|
LL | fn two(x: bool) -> impl Foo {
| -------- expected because this return type...
LL | if x {
LL | return 1_i32;
| ----- expected because of this statement
| ----- ...is found to be `i32` here
LL | }
LL | 0_u32
| ^^^^^ expected i32, found u32

View File

@ -5,10 +5,9 @@ LL | pub enum SomeEnum {
| ----------------- variant `A` not found here
LL | B = SomeEnum::A,
| ----------^
| |
| | |
| | help: did you mean: `B`
| variant not found in `SomeEnum`
|
= help: did you mean `B`?
error: aborting due to previous error

View File

@ -11,8 +11,7 @@ LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
| --------^^^^^
| |
| function or associated item not found in `dyn std::ops::BitXor<_>`
|
= help: did you mean `bitxor`?
| help: did you mean: `bitxor`
error[E0191]: the value of the associated type `Output` (from the trait `std::ops::BitXor`) must be specified
--> $DIR/issue-28344.rs:8:13
@ -27,8 +26,7 @@ LL | let g = BitXor::bitor;
| --------^^^^^
| |
| function or associated item not found in `dyn std::ops::BitXor<_>`
|
= help: did you mean `bitxor`?
| help: did you mean: `bitxor`
error: aborting due to 4 previous errors

View File

@ -5,9 +5,10 @@ LL | enum Foo {
| -------- variant `Baz` not found here
...
LL | Foo::Baz(..) => (),
| -----^^^---- variant not found in `Foo`
|
= help: did you mean `Bar`?
| -----^^^----
| | |
| | help: did you mean: `Bar`
| variant not found in `Foo`
error: aborting due to previous error

View File

@ -2,11 +2,10 @@ error[E0599]: no method named `deref_err` found for type `std::result::Result<_,
--> $DIR/result-deref-err.rs:4:28
|
LL | let _result = &Err(41).deref_err();
| ^^^^^^^^^
| ^^^^^^^^^ help: did you mean: `deref_ok`
|
= note: the method `deref_err` exists but the following trait bounds were not satisfied:
`{integer} : std::ops::Deref`
= help: did you mean `deref_ok`?
error: aborting due to previous error

View File

@ -0,0 +1,12 @@
struct Foo { bar: f64, baz: i64, bat: i64 }
fn main() {
let _ = Foo { bar: .5, baz: 42 };
//~^ ERROR float literals must have an integer part
//~| ERROR missing field `bat` in initializer of `Foo`
let bar = 1.5f32;
let _ = Foo { bar.into(), bat: -1, . };
//~^ ERROR expected one of
//~| ERROR missing fields `bar`, `baz` in initializer of `Foo`
//~| ERROR expected identifier, found `.`
}

View File

@ -0,0 +1,37 @@
error: float literals must have an integer part
--> $DIR/issue-52496.rs:4:24
|
LL | let _ = Foo { bar: .5, baz: 42 };
| ^^ help: must have an integer part: `0.5`
error: expected one of `,` or `}`, found `.`
--> $DIR/issue-52496.rs:8:22
|
LL | let _ = Foo { bar.into(), bat: -1, . };
| --- ^ expected one of `,` or `}` here
| |
| while parsing this struct
error: expected identifier, found `.`
--> $DIR/issue-52496.rs:8:40
|
LL | let _ = Foo { bar.into(), bat: -1, . };
| --- ^ expected identifier
| |
| while parsing this struct
error[E0063]: missing field `bat` in initializer of `Foo`
--> $DIR/issue-52496.rs:4:13
|
LL | let _ = Foo { bar: .5, baz: 42 };
| ^^^ missing `bat`
error[E0063]: missing fields `bar`, `baz` in initializer of `Foo`
--> $DIR/issue-52496.rs:8:13
|
LL | let _ = Foo { bar.into(), bat: -1, . };
| ^^^ missing `bar`, `baz`
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0063`.

View File

@ -0,0 +1,16 @@
// compile-pass
// This test checks that the `remove extra angle brackets` error doesn't happen for some
// potential edge-cases..
struct X {
len: u32,
}
fn main() {
let x = X { len: 3 };
let _ = x.len > (3);
let _ = x.len >> (3);
}

View File

@ -0,0 +1,22 @@
// run-rustfix
// This test checks that the following error is emitted and the suggestion works:
//
// ```
// let _ = Vec::<usize>>>::new();
// ^^ help: remove extra angle brackets
// ```
fn main() {
let _ = Vec::<usize>::new();
//~^ ERROR unmatched angle bracket
let _ = Vec::<usize>::new();
//~^ ERROR unmatched angle bracket
let _ = Vec::<usize>::new();
//~^ ERROR unmatched angle bracket
let _ = Vec::<usize>::new();
//~^ ERROR unmatched angle bracket
}

View File

@ -0,0 +1,22 @@
// run-rustfix
// This test checks that the following error is emitted and the suggestion works:
//
// ```
// let _ = Vec::<usize>>>::new();
// ^^ help: remove extra angle brackets
// ```
fn main() {
let _ = Vec::<usize>>>>>::new();
//~^ ERROR unmatched angle bracket
let _ = Vec::<usize>>>>::new();
//~^ ERROR unmatched angle bracket
let _ = Vec::<usize>>>::new();
//~^ ERROR unmatched angle bracket
let _ = Vec::<usize>>::new();
//~^ ERROR unmatched angle bracket
}

View File

@ -0,0 +1,26 @@
error: unmatched angle brackets
--> $DIR/issue-54521-2.rs:11:25
|
LL | let _ = Vec::<usize>>>>>::new();
| ^^^^ help: remove extra angle brackets
error: unmatched angle brackets
--> $DIR/issue-54521-2.rs:14:25
|
LL | let _ = Vec::<usize>>>>::new();
| ^^^ help: remove extra angle brackets
error: unmatched angle brackets
--> $DIR/issue-54521-2.rs:17:25
|
LL | let _ = Vec::<usize>>>::new();
| ^^ help: remove extra angle brackets
error: unmatched angle bracket
--> $DIR/issue-54521-2.rs:20:25
|
LL | let _ = Vec::<usize>>::new();
| ^ help: remove extra angle bracket
error: aborting due to 4 previous errors

View File

@ -0,0 +1,22 @@
// run-rustfix
// This test checks that the following error is emitted and the suggestion works:
//
// ```
// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
// ^^ help: remove extra angle brackets
// ```
fn main() {
let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
//~^ ERROR unmatched angle bracket
let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
//~^ ERROR unmatched angle bracket
let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
//~^ ERROR unmatched angle bracket
let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
//~^ ERROR unmatched angle bracket
}

View File

@ -0,0 +1,22 @@
// run-rustfix
// This test checks that the following error is emitted and the suggestion works:
//
// ```
// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
// ^^ help: remove extra angle brackets
// ```
fn main() {
let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>>();
//~^ ERROR unmatched angle bracket
let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>();
//~^ ERROR unmatched angle bracket
let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
//~^ ERROR unmatched angle bracket
let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>();
//~^ ERROR unmatched angle bracket
}

View File

@ -0,0 +1,26 @@
error: unmatched angle brackets
--> $DIR/issue-54521.rs:11:60
|
LL | let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>>();
| ^^^^ help: remove extra angle brackets
error: unmatched angle brackets
--> $DIR/issue-54521.rs:14:60
|
LL | let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>();
| ^^^ help: remove extra angle brackets
error: unmatched angle brackets
--> $DIR/issue-54521.rs:17:60
|
LL | let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
| ^^ help: remove extra angle brackets
error: unmatched angle bracket
--> $DIR/issue-54521.rs:20:60
|
LL | let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>();
| ^ help: remove extra angle bracket
error: aborting due to 4 previous errors

View File

@ -1,6 +1,6 @@
const
mut //~ ERROR: const globals cannot be mutable
//~^ HELP did you mean to declare a static?
//~^^ HELP you might want to declare a static instead
FOO: usize = 3;
fn main() {

View File

@ -1,10 +1,10 @@
error: const globals cannot be mutable
--> $DIR/issue-17718-const-mut.rs:2:1
|
LL | const
| ----- help: you might want to declare a static instead: `static`
LL | mut //~ ERROR: const globals cannot be mutable
| ^^^
|
= help: did you mean to declare a static?
| ^^^ cannot be mutable
error: aborting due to previous error

View File

@ -5,7 +5,6 @@ fn main() {
}
let a = S { foo: (), bar: () };
let b = S { foo: () with a };
let b = S { foo: () with a, bar: () };
//~^ ERROR expected one of `,`, `.`, `?`, `}`, or an operator, found `with`
//~| ERROR missing field `bar` in initializer of `main::S`
}

View File

@ -1,15 +1,10 @@
error: expected one of `,`, `.`, `?`, `}`, or an operator, found `with`
--> $DIR/removed-syntax-with-1.rs:8:25
|
LL | let b = S { foo: () with a };
| ^^^^ expected one of `,`, `.`, `?`, `}`, or an operator here
LL | let b = S { foo: () with a, bar: () };
| - ^^^^ expected one of `,`, `.`, `?`, `}`, or an operator here
| |
| while parsing this struct
error[E0063]: missing field `bar` in initializer of `main::S`
--> $DIR/removed-syntax-with-1.rs:8:13
|
LL | let b = S { foo: () with a };
| ^ missing `bar`
error: aborting due to previous error
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0063`.

View File

@ -7,6 +7,5 @@ fn main() {
let a = S { foo: (), bar: () };
let b = S { foo: (), with a };
//~^ ERROR expected one of `,` or `}`, found `a`
//~| ERROR cannot find value `with` in this scope
//~| ERROR struct `main::S` has no field named `with`
//~| ERROR missing field `bar` in initializer of `main::S`
}

View File

@ -2,23 +2,16 @@ error: expected one of `,` or `}`, found `a`
--> $DIR/removed-syntax-with-2.rs:8:31
|
LL | let b = S { foo: (), with a };
| ^ expected one of `,` or `}` here
| - ^ expected one of `,` or `}` here
| |
| while parsing this struct
error[E0425]: cannot find value `with` in this scope
--> $DIR/removed-syntax-with-2.rs:8:26
error[E0063]: missing field `bar` in initializer of `main::S`
--> $DIR/removed-syntax-with-2.rs:8:13
|
LL | let b = S { foo: (), with a };
| ^^^^ not found in this scope
| ^ missing `bar`
error[E0560]: struct `main::S` has no field named `with`
--> $DIR/removed-syntax-with-2.rs:8:26
|
LL | let b = S { foo: (), with a };
| ^^^^ `main::S` does not have this field
|
= note: available fields are: `foo`, `bar`
error: aborting due to 2 previous errors
error: aborting due to 3 previous errors
Some errors occurred: E0425, E0560.
For more information about an error, try `rustc --explain E0425`.
For more information about this error, try `rustc --explain E0063`.

View File

@ -1,6 +1,9 @@
struct Rgb(u8, u8, u8);
fn main() {
let _ = Rgb { 0, 1, 2 }; //~ ERROR expected identifier, found `0`
//~| ERROR missing fields `0`, `1`, `2` in initializer of `Rgb`
let _ = Rgb { 0, 1, 2 };
//~^ ERROR expected identifier, found `0`
//~| ERROR expected identifier, found `1`
//~| ERROR expected identifier, found `2`
//~| ERROR missing fields `0`, `1`, `2` in initializer of `Rgb`
}

View File

@ -1,17 +1,33 @@
error: expected identifier, found `0`
--> $DIR/struct-field-numeric-shorthand.rs:4:19
|
LL | let _ = Rgb { 0, 1, 2 }; //~ ERROR expected identifier, found `0`
LL | let _ = Rgb { 0, 1, 2 };
| --- ^ expected identifier
| |
| while parsing this struct
error: expected identifier, found `1`
--> $DIR/struct-field-numeric-shorthand.rs:4:22
|
LL | let _ = Rgb { 0, 1, 2 };
| --- ^ expected identifier
| |
| while parsing this struct
error: expected identifier, found `2`
--> $DIR/struct-field-numeric-shorthand.rs:4:25
|
LL | let _ = Rgb { 0, 1, 2 };
| --- ^ expected identifier
| |
| while parsing this struct
error[E0063]: missing fields `0`, `1`, `2` in initializer of `Rgb`
--> $DIR/struct-field-numeric-shorthand.rs:4:13
|
LL | let _ = Rgb { 0, 1, 2 }; //~ ERROR expected identifier, found `0`
LL | let _ = Rgb { 0, 1, 2 };
| ^^^ missing `0`, `1`, `2`
error: aborting due to 2 previous errors
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0063`.

View File

@ -1,8 +1,11 @@
error[E0308]: mismatched types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:5:5
|
LL | fn foo() -> impl std::fmt::Display {
| ---------------------- expected because this return type...
LL | if false {
LL | return 0i32;
| ---- expected because of this statement
| ---- ...is found to be `i32` here
LL | }
LL | 1u32
| ^^^^ expected i32, found u32
@ -13,8 +16,11 @@ LL | 1u32
error[E0308]: mismatched types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:13:16
|
LL | fn bar() -> impl std::fmt::Display {
| ---------------------- expected because this return type...
LL | if false {
LL | return 0i32;
| ---- expected because of this statement
| ---- ...is found to be `i32` here
LL | } else {
LL | return 1u32;
| ^^^^ expected i32, found u32
@ -25,10 +31,12 @@ LL | return 1u32;
error[E0308]: mismatched types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:19:5
|
LL | fn baz() -> impl std::fmt::Display {
| ---------------------- expected because this return type...
LL | / if false {
LL | | //~^ ERROR mismatched types
LL | | return 0i32;
| | ---- expected because of this statement
| | ---- ...is found to be `i32` here
LL | | } else {
LL | | 1u32
LL | | }

View File

@ -0,0 +1,11 @@
fn main() {
let _: usize = .3;
//~^ ERROR float literals must have an integer part
//~| ERROR mismatched types
let _: usize = .42f32;
//~^ ERROR float literals must have an integer part
//~| ERROR mismatched types
let _: usize = .5f64;
//~^ ERROR float literals must have an integer part
//~| ERROR mismatched types
}

View File

@ -0,0 +1,42 @@
error: float literals must have an integer part
--> $DIR/recover-invalid-float.rs:2:20
|
LL | let _: usize = .3;
| ^^ help: must have an integer part: `0.3`
error: float literals must have an integer part
--> $DIR/recover-invalid-float.rs:5:20
|
LL | let _: usize = .42f32;
| ^^^^^^ help: must have an integer part: `0.42f32`
error: float literals must have an integer part
--> $DIR/recover-invalid-float.rs:8:20
|
LL | let _: usize = .5f64;
| ^^^^^ help: must have an integer part: `0.5f64`
error[E0308]: mismatched types
--> $DIR/recover-invalid-float.rs:2:20
|
LL | let _: usize = .3;
| ^^ expected usize, found floating-point number
|
= note: expected type `usize`
found type `{float}`
error[E0308]: mismatched types
--> $DIR/recover-invalid-float.rs:5:20
|
LL | let _: usize = .42f32;
| ^^^^^^ expected usize, found f32
error[E0308]: mismatched types
--> $DIR/recover-invalid-float.rs:8:20
|
LL | let _: usize = .5f64;
| ^^^^^ expected usize, found f64
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0308`.

View File

@ -5,25 +5,19 @@ LL | struct Foo;
| ----------- method `bat` not found for this
...
LL | f.bat(1.0); //~ ERROR no method named
| ^^^
|
= help: did you mean `bar`?
| ^^^ help: did you mean: `bar`
error[E0599]: no method named `is_emtpy` found for type `std::string::String` in the current scope
--> $DIR/suggest-methods.rs:21:15
|
LL | let _ = s.is_emtpy(); //~ ERROR no method named
| ^^^^^^^^
|
= help: did you mean `is_empty`?
| ^^^^^^^^ help: did you mean: `is_empty`
error[E0599]: no method named `count_eos` found for type `u32` in the current scope
--> $DIR/suggest-methods.rs:25:19
|
LL | let _ = 63u32.count_eos(); //~ ERROR no method named
| ^^^^^^^^^
|
= help: did you mean `count_zeros`?
| ^^^^^^^^^ help: did you mean: `count_zeros`
error[E0599]: no method named `count_o` found for type `u32` in the current scope
--> $DIR/suggest-methods.rs:28:19

View File

@ -1,5 +1,4 @@
// compile-pass
#![feature(get_type_id)]
#![allow(dead_code)]
mod foo {
pub use self::bar::T;
@ -18,7 +17,7 @@ fn g() {
fn f() {
let error = ::std::thread::spawn(|| {}).join().unwrap_err();
error.get_type_id(); // Regression test for #21670
error.type_id(); // Regression test for #21670
}