mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-13 09:05:00 +00:00
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:
commit
cd3d580d59
4
.gitattributes
vendored
4
.gitattributes
vendored
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
12
src/test/ui/existential_types/auxiliary/cross_crate_ice.rs
Normal file
12
src/test/ui/existential_types/auxiliary/cross_crate_ice.rs
Normal 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
|
||||
}
|
||||
|
21
src/test/ui/existential_types/auxiliary/cross_crate_ice2.rs
Normal file
21
src/test/ui/existential_types/auxiliary/cross_crate_ice2.rs
Normal 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()
|
||||
}
|
||||
}
|
16
src/test/ui/existential_types/cross_crate_ice.rs
Normal file
16
src/test/ui/existential_types/cross_crate_ice.rs
Normal 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();
|
||||
}
|
11
src/test/ui/existential_types/cross_crate_ice2.rs
Normal file
11
src/test/ui/existential_types/cross_crate_ice2.rs
Normal 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();
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
12
src/test/ui/issues/issue-52496.rs
Normal file
12
src/test/ui/issues/issue-52496.rs
Normal 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 `.`
|
||||
}
|
37
src/test/ui/issues/issue-52496.stderr
Normal file
37
src/test/ui/issues/issue-52496.stderr
Normal 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`.
|
16
src/test/ui/issues/issue-54521-1.rs
Normal file
16
src/test/ui/issues/issue-54521-1.rs
Normal 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);
|
||||
}
|
22
src/test/ui/issues/issue-54521-2.fixed
Normal file
22
src/test/ui/issues/issue-54521-2.fixed
Normal 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
|
||||
}
|
22
src/test/ui/issues/issue-54521-2.rs
Normal file
22
src/test/ui/issues/issue-54521-2.rs
Normal 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
|
||||
}
|
26
src/test/ui/issues/issue-54521-2.stderr
Normal file
26
src/test/ui/issues/issue-54521-2.stderr
Normal 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
|
||||
|
22
src/test/ui/issues/issue-54521.fixed
Normal file
22
src/test/ui/issues/issue-54521.fixed
Normal 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
|
||||
}
|
22
src/test/ui/issues/issue-54521.rs
Normal file
22
src/test/ui/issues/issue-54521.rs
Normal 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
|
||||
}
|
26
src/test/ui/issues/issue-54521.stderr
Normal file
26
src/test/ui/issues/issue-54521.stderr
Normal 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
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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`
|
||||
}
|
||||
|
@ -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`.
|
||||
|
@ -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`
|
||||
}
|
||||
|
@ -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`.
|
||||
|
@ -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`
|
||||
}
|
||||
|
@ -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`.
|
||||
|
@ -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 | | }
|
||||
|
11
src/test/ui/suggestions/recover-invalid-float.rs
Normal file
11
src/test/ui/suggestions/recover-invalid-float.rs
Normal 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
|
||||
}
|
42
src/test/ui/suggestions/recover-invalid-float.stderr
Normal file
42
src/test/ui/suggestions/recover-invalid-float.stderr
Normal 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`.
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user