diff --git a/Cargo.lock b/Cargo.lock index a6dca2048d4e8..0f770f3eadbea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3762,7 +3762,6 @@ dependencies = [ "rustc", "rustc_codegen_utils", "rustc_data_structures", - "rustc_target", "serde_json", "syntax", "syntax_pos", @@ -4362,7 +4361,6 @@ dependencies = [ "rustc_errors", "rustc_index", "rustc_lexer", - "rustc_target", "scoped-tls", "serialize", "smallvec 1.0.0", @@ -4380,7 +4378,6 @@ dependencies = [ "rustc_errors", "rustc_index", "rustc_lexer", - "rustc_target", "scoped-tls", "serialize", "smallvec 1.0.0", diff --git a/src/libcore/iter/traits/collect.rs b/src/libcore/iter/traits/collect.rs index 00a864170583e..bbdb169cac0fc 100644 --- a/src/libcore/iter/traits/collect.rs +++ b/src/libcore/iter/traits/collect.rs @@ -205,6 +205,7 @@ pub trait FromIterator: Sized { /// .collect() /// } /// ``` +#[rustc_diagnostic_item = "IntoIterator"] #[stable(feature = "rust1", since = "1.0.0")] pub trait IntoIterator { /// The type of the elements being iterated over. diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 18d98efebd42f..f40b892a06bf2 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -2336,6 +2336,7 @@ the future, [RFC 2091] prohibits their implementation without a follow-up RFC. E0657, // `impl Trait` can only capture lifetimes bound at the fn level E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders + E0703, // invalid ABI // E0707, // multiple elided lifetimes used in arguments of `async fn` E0708, // `async` non-`move` closures with parameters are not currently // supported diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 230fbb16b87bc..6344c7a233ca4 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1216,7 +1216,7 @@ impl<'a> LoweringContext<'a> { ImplTraitContext::disallowed(), ), unsafety: this.lower_unsafety(f.unsafety), - abi: f.abi, + abi: this.lower_abi(f.abi), decl: this.lower_fn_decl(&f.decl, None, false, None), param_names: this.lower_fn_params_to_names(&f.decl), })) diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index f1b999cdd6f0f..5fe463d783f4b 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -12,6 +12,7 @@ use crate::hir::def::{Res, DefKind}; use crate::util::nodemap::NodeMap; use rustc_data_structures::thin_vec::ThinVec; +use rustc_target::spec::abi; use std::collections::BTreeSet; use smallvec::SmallVec; @@ -735,7 +736,7 @@ impl LoweringContext<'_> { fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod { hir::ForeignMod { - abi: fm.abi, + abi: self.lower_abi(fm.abi), items: fm.items .iter() .map(|x| self.lower_foreign_item(x)) @@ -1291,10 +1292,30 @@ impl LoweringContext<'_> { unsafety: self.lower_unsafety(h.unsafety), asyncness: self.lower_asyncness(h.asyncness.node), constness: self.lower_constness(h.constness), - abi: h.abi, + abi: self.lower_abi(h.abi), } } + pub(super) fn lower_abi(&mut self, abi: Abi) -> abi::Abi { + abi::lookup(&abi.symbol.as_str()).unwrap_or_else(|| { + self.error_on_invalid_abi(abi); + abi::Abi::Rust + }) + } + + fn error_on_invalid_abi(&self, abi: Abi) { + struct_span_err!( + self.sess, + abi.span, + E0703, + "invalid ABI: found `{}`", + abi.symbol + ) + .span_label(abi.span, "invalid ABI") + .help(&format!("valid ABIs: {}", abi::all_names().join(", "))) + .emit(); + } + pub(super) fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety { match u { Unsafety::Unsafe => hir::Unsafety::Unsafe, diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index d6f7ba6b9734e..d409ca6f3c5f5 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1075,6 +1075,13 @@ impl Mutability { MutImmutable => MutMutable, } } + + pub fn prefix_str(&self) -> &'static str { + match self { + MutMutable => "mut ", + MutImmutable => "", + } + } } #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] @@ -2184,6 +2191,15 @@ pub enum Unsafety { Normal, } +impl Unsafety { + pub fn prefix_str(&self) -> &'static str { + match self { + Unsafety::Unsafe => "unsafe ", + Unsafety::Normal => "", + } + } +} + #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum Constness { Const, diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 328d475be0606..a25c111b59871 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1734,9 +1734,7 @@ impl<'a> State<'a> { _ => false, }; self.s.word("&"); - if mutbl == hir::MutMutable { - self.s.word("mut "); - } + self.s.word(mutbl.prefix_str()); if is_range_inner { self.popen(); } diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index aa147462e3d3b..2201c4b0980b3 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -124,7 +124,6 @@ for ::syntax::attr::StabilityLevel { impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason, suggestion }); - impl_stable_hash_for!(enum ::syntax::attr::IntType { SignedInt(int_ty), UnsignedInt(uint_ty) @@ -136,6 +135,11 @@ impl_stable_hash_for!(enum ::syntax::ast::LitIntType { Unsuffixed }); +impl_stable_hash_for!(enum ::syntax::ast::LitFloatType { + Suffixed(float_ty), + Unsuffixed +}); + impl_stable_hash_for!(struct ::syntax::ast::Lit { kind, token, @@ -148,8 +152,7 @@ impl_stable_hash_for!(enum ::syntax::ast::LitKind { Byte(value), Char(value), Int(value, lit_int_type), - Float(value, float_ty), - FloatUnsuffixed(value), + Float(value, lit_float_type), Bool(value), Err(value) }); @@ -159,6 +162,7 @@ impl_stable_hash_for_spanned!(::syntax::ast::LitKind); impl_stable_hash_for!(enum ::syntax::ast::IntTy { Isize, I8, I16, I32, I64, I128 }); impl_stable_hash_for!(enum ::syntax::ast::UintTy { Usize, U8, U16, U32, U64, U128 }); impl_stable_hash_for!(enum ::syntax::ast::FloatTy { F32, F64 }); +impl_stable_hash_for!(enum ::rustc_target::abi::FloatTy { F32, F64 }); impl_stable_hash_for!(enum ::syntax::ast::Unsafety { Unsafe, Normal }); impl_stable_hash_for!(enum ::syntax::ast::Constness { Const, NotConst }); impl_stable_hash_for!(enum ::syntax::ast::Defaultness { Default, Final }); diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index e238c96612234..38edef50c9662 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -897,11 +897,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } else { r.push(' '); } - s.push_highlighted(format!( - "&{}{}", - r, - if mutbl == hir::MutMutable { "mut " } else { "" } - )); + s.push_highlighted(format!("&{}{}", r, mutbl.prefix_str())); s.push_normal(ty.to_string()); } diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 95040135eb7d3..60aab6b6aa924 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -538,7 +538,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { ty::Uint(ity) => { scalar(Int(Integer::from_attr(dl, attr::UnsignedInt(ity)), false)) } - ty::Float(fty) => scalar(Float(fty)), + ty::Float(fty) => scalar(Float(match fty { + ast::FloatTy::F32 => FloatTy::F32, + ast::FloatTy::F64 => FloatTy::F64, + })), ty::FnPtr(_) => { let mut ptr = scalar_unit(Pointer); ptr.valid_range = 1..=*ptr.valid_range.end(); diff --git a/src/librustc/ty/print/obsolete.rs b/src/librustc/ty/print/obsolete.rs index e72916de6a9c7..ddbba972e51a7 100644 --- a/src/librustc/ty/print/obsolete.rs +++ b/src/librustc/ty/print/obsolete.rs @@ -12,7 +12,6 @@ use rustc::ty::{self, Const, Instance, Ty, TyCtxt}; use rustc::{bug, hir}; use std::fmt::Write; use std::iter; -use syntax::ast; /// Same as `unique_type_name()` but with the result pushed onto the given /// `output` parameter. @@ -39,20 +38,9 @@ impl DefPathBasedNames<'tcx> { ty::Char => output.push_str("char"), ty::Str => output.push_str("str"), ty::Never => output.push_str("!"), - ty::Int(ast::IntTy::Isize) => output.push_str("isize"), - ty::Int(ast::IntTy::I8) => output.push_str("i8"), - ty::Int(ast::IntTy::I16) => output.push_str("i16"), - ty::Int(ast::IntTy::I32) => output.push_str("i32"), - ty::Int(ast::IntTy::I64) => output.push_str("i64"), - ty::Int(ast::IntTy::I128) => output.push_str("i128"), - ty::Uint(ast::UintTy::Usize) => output.push_str("usize"), - ty::Uint(ast::UintTy::U8) => output.push_str("u8"), - ty::Uint(ast::UintTy::U16) => output.push_str("u16"), - ty::Uint(ast::UintTy::U32) => output.push_str("u32"), - ty::Uint(ast::UintTy::U64) => output.push_str("u64"), - ty::Uint(ast::UintTy::U128) => output.push_str("u128"), - ty::Float(ast::FloatTy::F32) => output.push_str("f32"), - ty::Float(ast::FloatTy::F64) => output.push_str("f64"), + ty::Int(ty) => output.push_str(ty.name_str()), + ty::Uint(ty) => output.push_str(ty.name_str()), + ty::Float(ty) => output.push_str(ty.name_str()), ty::Adt(adt_def, substs) => { self.push_def_path(adt_def.did, output); self.push_generic_params(substs, iter::empty(), output, debug); @@ -80,9 +68,7 @@ impl DefPathBasedNames<'tcx> { } ty::Ref(_, inner_type, mutbl) => { output.push('&'); - if mutbl == hir::MutMutable { - output.push_str("mut "); - } + output.push_str(mutbl.prefix_str()); self.push_type_name(inner_type, output, debug); } @@ -114,9 +100,7 @@ impl DefPathBasedNames<'tcx> { ty::Foreign(did) => self.push_def_path(did, output), ty::FnDef(..) | ty::FnPtr(_) => { let sig = t.fn_sig(self.tcx); - if sig.unsafety() == hir::Unsafety::Unsafe { - output.push_str("unsafe "); - } + output.push_str(sig.unsafety().prefix_str()); let abi = sig.abi(); if abi != ::rustc_target::spec::abi::Abi::Rust { diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 8a98a5d83615f..4c75e47401138 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -466,9 +466,9 @@ pub trait PrettyPrinter<'tcx>: match ty.kind { ty::Bool => p!(write("bool")), ty::Char => p!(write("char")), - ty::Int(t) => p!(write("{}", t.ty_to_string())), - ty::Uint(t) => p!(write("{}", t.ty_to_string())), - ty::Float(t) => p!(write("{}", t.ty_to_string())), + ty::Int(t) => p!(write("{}", t.name_str())), + ty::Uint(t) => p!(write("{}", t.name_str())), + ty::Float(t) => p!(write("{}", t.name_str())), ty::RawPtr(ref tm) => { p!(write("*{} ", match tm.mutbl { hir::MutMutable => "mut", @@ -895,10 +895,11 @@ pub trait PrettyPrinter<'tcx>: let bit_size = Integer::from_attr(&self.tcx(), UnsignedInt(*ui)).size(); let max = truncate(u128::max_value(), bit_size); + let ui_str = ui.name_str(); if data == max { - p!(write("std::{}::MAX", ui)) + p!(write("std::{}::MAX", ui_str)) } else { - p!(write("{}{}", data, ui)) + p!(write("{}{}", data, ui_str)) }; }, (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Int(i)) => { @@ -911,10 +912,11 @@ pub trait PrettyPrinter<'tcx>: let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty)) .unwrap() .size; + let i_str = i.name_str(); match data { - d if d == min => p!(write("std::{}::MIN", i)), - d if d == max => p!(write("std::{}::MAX", i)), - _ => p!(write("{}{}", sign_extend(data, size) as i128, i)) + d if d == min => p!(write("std::{}::MIN", i_str)), + d if d == max => p!(write("std::{}::MAX", i_str)), + _ => p!(write("{}{}", sign_extend(data, size) as i128, i_str)) } }, (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Char) => @@ -1666,8 +1668,7 @@ define_print_and_forward_display! { } ty::TypeAndMut<'tcx> { - p!(write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }), - print(self.ty)) + p!(write("{}", self.mutbl.prefix_str()), print(self.ty)) } ty::ExistentialTraitRef<'tcx> { @@ -1693,9 +1694,7 @@ define_print_and_forward_display! { } ty::FnSig<'tcx> { - if self.unsafety == hir::Unsafety::Unsafe { - p!(write("unsafe ")); - } + p!(write("{}", self.unsafety.prefix_str())); if self.abi != Abi::Rust { p!(write("extern {} ", self.abi)); diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index f0148a21ae670..5f18bb1700c14 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -843,13 +843,13 @@ fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { ty::Bool => ("bool", DW_ATE_boolean), ty::Char => ("char", DW_ATE_unsigned_char), ty::Int(int_ty) => { - (int_ty.ty_to_string(), DW_ATE_signed) + (int_ty.name_str(), DW_ATE_signed) }, ty::Uint(uint_ty) => { - (uint_ty.ty_to_string(), DW_ATE_unsigned) + (uint_ty.name_str(), DW_ATE_unsigned) }, ty::Float(float_ty) => { - (float_ty.ty_to_string(), DW_ATE_float) + (float_ty.name_str(), DW_ATE_float) }, _ => bug!("debuginfo::basic_type_metadata - t is invalid type") }; diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 1bce34abe5599..a4c3b42f51e9e 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -18,8 +18,8 @@ use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Primitive}; use rustc::mir::interpret::GlobalId; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc::hir; -use syntax::ast::{self, FloatTy}; -use rustc_target::abi::HasDataLayout; +use rustc_target::abi::{FloatTy, HasDataLayout}; +use syntax::ast; use rustc_codegen_ssa::common::span_invalid_monomorphization_error; use rustc_codegen_ssa::traits::*; @@ -1335,7 +1335,7 @@ fn generic_simd_intrinsic( }, ty::Float(f) => { return_error!("unsupported element type `{}` of floating-point vector `{}`", - f, in_ty); + f.name_str(), in_ty); }, _ => { return_error!("`{}` is not a floating-point type", in_ty); diff --git a/src/librustc_codegen_ssa/debuginfo/type_names.rs b/src/librustc_codegen_ssa/debuginfo/type_names.rs index 166a74fe48795..f40b942b1e322 100644 --- a/src/librustc_codegen_ssa/debuginfo/type_names.rs +++ b/src/librustc_codegen_ssa/debuginfo/type_names.rs @@ -37,9 +37,9 @@ pub fn push_debuginfo_type_name<'tcx>( ty::Char => output.push_str("char"), ty::Str => output.push_str("str"), ty::Never => output.push_str("!"), - ty::Int(int_ty) => output.push_str(int_ty.ty_to_string()), - ty::Uint(uint_ty) => output.push_str(uint_ty.ty_to_string()), - ty::Float(float_ty) => output.push_str(float_ty.ty_to_string()), + ty::Int(int_ty) => output.push_str(int_ty.name_str()), + ty::Uint(uint_ty) => output.push_str(uint_ty.name_str()), + ty::Float(float_ty) => output.push_str(float_ty.name_str()), ty::Foreign(def_id) => push_item_name(tcx, def_id, qualified, output), ty::Adt(def, substs) => { push_item_name(tcx, def.did, qualified, output); @@ -76,9 +76,7 @@ pub fn push_debuginfo_type_name<'tcx>( if !cpp_like_names { output.push('&'); } - if mutbl == hir::MutMutable { - output.push_str("mut "); - } + output.push_str(mutbl.prefix_str()); push_debuginfo_type_name(tcx, inner_type, true, output, visited); @@ -140,9 +138,7 @@ pub fn push_debuginfo_type_name<'tcx>( let sig = t.fn_sig(tcx); - if sig.unsafety() == hir::Unsafety::Unsafe { - output.push_str("unsafe "); - } + output.push_str(sig.unsafety().prefix_str()); let abi = sig.abi(); if abi != rustc_target::spec::abi::Abi::Rust { diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml index 98e4f974a9f23..35b93db1d6590 100644 --- a/src/librustc_interface/Cargo.toml +++ b/src/librustc_interface/Cargo.toml @@ -27,7 +27,6 @@ rustc_codegen_utils = { path = "../librustc_codegen_utils" } rustc_metadata = { path = "../librustc_metadata" } rustc_mir = { path = "../librustc_mir" } rustc_passes = { path = "../librustc_passes" } -rustc_target = { path = "../librustc_target" } rustc_typeck = { path = "../librustc_typeck" } rustc_lint = { path = "../librustc_lint" } rustc_errors = { path = "../librustc_errors" } @@ -36,3 +35,6 @@ rustc_privacy = { path = "../librustc_privacy" } rustc_resolve = { path = "../librustc_resolve" } tempfile = "3.0.5" once_cell = "1" + +[dev-dependencies] +rustc_target = { path = "../librustc_target" } diff --git a/src/librustc_lint/array_into_iter.rs b/src/librustc_lint/array_into_iter.rs new file mode 100644 index 0000000000000..e73414174fb35 --- /dev/null +++ b/src/librustc_lint/array_into_iter.rs @@ -0,0 +1,91 @@ +use crate::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass}; +use rustc::{ + lint::FutureIncompatibleInfo, + hir, + ty::{ + self, + adjustment::{Adjust, Adjustment}, + }, +}; +use syntax::{ + errors::Applicability, + symbol::sym, +}; + + +declare_lint! { + pub ARRAY_INTO_ITER, + Warn, + "detects calling `into_iter` on arrays", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #66145 ", + edition: None, + }; +} + +declare_lint_pass!( + /// Checks for instances of calling `into_iter` on arrays. + ArrayIntoIter => [ARRAY_INTO_ITER] +); + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIntoIter { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { + // We only care about method call expressions. + if let hir::ExprKind::MethodCall(call, span, args) = &expr.kind { + if call.ident.name != sym::into_iter { + return; + } + + // Check if the method call actually calls the libcore + // `IntoIterator::into_iter`. + let def_id = cx.tables.type_dependent_def_id(expr.hir_id).unwrap(); + match cx.tcx.trait_of_item(def_id) { + Some(trait_id) if cx.tcx.is_diagnostic_item(sym::IntoIterator, trait_id) => {}, + _ => return, + }; + + // As this is a method call expression, we have at least one + // argument. + let receiver_arg = &args[0]; + + // Test if the original `self` type is an array type. + match cx.tables.expr_ty(receiver_arg).kind { + ty::Array(..) => {} + _ => return, + } + + // Make sure that the first adjustment is an autoref coercion. + match cx.tables.expr_adjustments(receiver_arg).get(0) { + Some(Adjustment { kind: Adjust::Borrow(_), .. }) => {} + _ => return, + } + + // Emit lint diagnostic. + let target = match cx.tables.expr_ty_adjusted(receiver_arg).kind { + ty::Ref(_, ty::TyS { kind: ty::Array(..), ..}, _) => "[T; N]", + ty::Ref(_, ty::TyS { kind: ty::Slice(..), ..}, _) => "[T]", + + // We know the original first argument type is an array type, + // we know that the first adjustment was an autoref coercion + // and we know that `IntoIterator` is the trait involved. The + // array cannot be coerced to something other than a reference + // to an array or to a slice. + _ => bug!("array type coerced to something other than array or slice"), + }; + let msg = format!( + "this method call currently resolves to `<&{} as IntoIterator>::into_iter` (due \ + to autoref coercions), but that might change in the future when \ + `IntoIterator` impls for arrays are added.", + target, + ); + cx.struct_span_lint(ARRAY_INTO_ITER, *span, &msg) + .span_suggestion( + call.ident.span, + "use `.iter()` instead of `.into_iter()` to avoid ambiguity", + "iter".into(), + Applicability::MachineApplicable, + ) + .emit(); + } + } +} diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index a47980c5ead30..d1dc1d0fb686d 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -22,6 +22,7 @@ #[macro_use] extern crate rustc; +mod array_into_iter; mod error_codes; mod nonstandard_style; mod redundant_semicolon; @@ -57,6 +58,7 @@ use types::*; use unused::*; use non_ascii_idents::*; use rustc::lint::internal::*; +use array_into_iter::ArrayIntoIter; /// Useful for other parts of the compiler. pub use builtin::SoftLints; @@ -131,6 +133,8 @@ macro_rules! late_lint_passes { // FIXME: Turn the computation of types which implement Debug into a query // and change this to a module lint pass MissingDebugImplementations: MissingDebugImplementations::default(), + + ArrayIntoIter: ArrayIntoIter, ]); ) } diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index f2ad400d5dd37..65e0940920bd7 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -68,7 +68,7 @@ fn lint_overflowing_range_endpoint<'a, 'tcx>( max: u128, expr: &'tcx hir::Expr, parent_expr: &'tcx hir::Expr, - ty: impl std::fmt::Debug, + ty: &str, ) -> bool { // We only want to handle exclusive (`..`) ranges, // which are represented as `ExprKind::Struct`. @@ -83,15 +83,15 @@ fn lint_overflowing_range_endpoint<'a, 'tcx>( let mut err = cx.struct_span_lint( OVERFLOWING_LITERALS, parent_expr.span, - &format!("range endpoint is out of range for `{:?}`", ty), + &format!("range endpoint is out of range for `{}`", ty), ); if let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) { use ast::{LitKind, LitIntType}; // We need to preserve the literal's suffix, // as it may determine typing information. let suffix = match lit.node { - LitKind::Int(_, LitIntType::Signed(s)) => format!("{}", s), - LitKind::Int(_, LitIntType::Unsigned(s)) => format!("{}", s), + LitKind::Int(_, LitIntType::Signed(s)) => format!("{}", s.name_str()), + LitKind::Int(_, LitIntType::Unsigned(s)) => format!("{}", s.name_str()), LitKind::Int(_, LitIntType::Unsuffixed) => "".to_owned(), _ => bug!(), }; @@ -161,11 +161,11 @@ fn report_bin_hex_error( let (t, actually) = match ty { attr::IntType::SignedInt(t) => { let actually = sign_extend(val, size) as i128; - (format!("{:?}", t), actually.to_string()) + (t.name_str(), actually.to_string()) } attr::IntType::UnsignedInt(t) => { let actually = truncate(val, size); - (format!("{:?}", t), actually.to_string()) + (t.name_str(), actually.to_string()) } }; let mut err = cx.struct_span_lint( @@ -204,7 +204,7 @@ fn report_bin_hex_error( // - `uX` => `uY` // // No suggestion for: `isize`, `usize`. -fn get_type_suggestion(t: Ty<'_>, val: u128, negative: bool) -> Option { +fn get_type_suggestion(t: Ty<'_>, val: u128, negative: bool) -> Option<&'static str> { use syntax::ast::IntTy::*; use syntax::ast::UintTy::*; macro_rules! find_fit { @@ -215,10 +215,10 @@ fn get_type_suggestion(t: Ty<'_>, val: u128, negative: bool) -> Option { match $ty { $($type => { $(if !negative && val <= uint_ty_range($utypes).1 { - return Some(format!("{:?}", $utypes)) + return Some($utypes.name_str()) })* $(if val <= int_ty_range($itypes).1 as u128 + _neg { - return Some(format!("{:?}", $itypes)) + return Some($itypes.name_str()) })* None },)+ @@ -281,7 +281,7 @@ fn lint_int_literal<'a, 'tcx>( if let Node::Expr(par_e) = cx.tcx.hir().get(par_id) { if let hir::ExprKind::Struct(..) = par_e.kind { if is_range_literal(cx.sess(), par_e) - && lint_overflowing_range_endpoint(cx, lit, v, max, e, par_e, t) + && lint_overflowing_range_endpoint(cx, lit, v, max, e, par_e, t.name_str()) { // The overflowing literal lint was overridden. return; @@ -292,7 +292,7 @@ fn lint_int_literal<'a, 'tcx>( cx.span_lint( OVERFLOWING_LITERALS, e.span, - &format!("literal out of range for `{:?}`", t), + &format!("literal out of range for `{}`", t.name_str()), ); } } @@ -338,6 +338,7 @@ fn lint_uint_literal<'a, 'tcx>( } hir::ExprKind::Struct(..) if is_range_literal(cx.sess(), par_e) => { + let t = t.name_str(); if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, par_e, t) { // The overflowing literal lint was overridden. return; @@ -353,7 +354,7 @@ fn lint_uint_literal<'a, 'tcx>( cx.span_lint( OVERFLOWING_LITERALS, e.span, - &format!("literal out of range for `{:?}`", t), + &format!("literal out of range for `{}`", t.name_str()), ); } } @@ -379,8 +380,7 @@ fn lint_literal<'a, 'tcx>( } ty::Float(t) => { let is_infinite = match lit.node { - ast::LitKind::Float(v, _) | - ast::LitKind::FloatUnsuffixed(v) => { + ast::LitKind::Float(v, _) => { match t { ast::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite), ast::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite), @@ -389,9 +389,11 @@ fn lint_literal<'a, 'tcx>( _ => bug!(), }; if is_infinite == Ok(true) { - cx.span_lint(OVERFLOWING_LITERALS, - e.span, - &format!("literal out of range for `{:?}`", t)); + cx.span_lint( + OVERFLOWING_LITERALS, + e.span, + &format!("literal out of range for `{}`", t.name_str()), + ); } } _ => {} diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index c5f830c0d0420..b01b99ffcfb09 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -95,8 +95,8 @@ provide! { <'tcx> tcx, def_id, other, cdata, generics_of => { tcx.arena.alloc(cdata.get_generics(def_id.index, tcx.sess)) } - predicates_of => { cdata.get_predicates(def_id.index, tcx) } - predicates_defined_on => { cdata.get_predicates_defined_on(def_id.index, tcx) } + explicit_predicates_of => { cdata.get_explicit_predicates(def_id.index, tcx) } + inferred_outlives_of => { cdata.get_inferred_outlives(def_id.index, tcx) } super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) } trait_def => { tcx.arena.alloc(cdata.get_trait_def(def_id.index, tcx.sess)) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index c5954e1ea1d98..771d01a4b6a1d 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -658,20 +658,22 @@ impl<'a, 'tcx> CrateMetadata { tcx.alloc_adt_def(did, adt_kind, variants, repr) } - crate fn get_predicates( + crate fn get_explicit_predicates( &self, item_id: DefIndex, tcx: TyCtxt<'tcx>, ) -> ty::GenericPredicates<'tcx> { - self.root.per_def.predicates.get(self, item_id).unwrap().decode((self, tcx)) + self.root.per_def.explicit_predicates.get(self, item_id).unwrap().decode((self, tcx)) } - crate fn get_predicates_defined_on( + crate fn get_inferred_outlives( &self, item_id: DefIndex, tcx: TyCtxt<'tcx>, - ) -> ty::GenericPredicates<'tcx> { - self.root.per_def.predicates_defined_on.get(self, item_id).unwrap().decode((self, tcx)) + ) -> &'tcx [(ty::Predicate<'tcx>, Span)] { + self.root.per_def.inferred_outlives.get(self, item_id).map(|predicates| { + predicates.decode((self, tcx)) + }).unwrap_or_default() } crate fn get_super_predicates( diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index de00e9920e683..618d342f6fe75 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -76,8 +76,8 @@ struct PerDefTables<'tcx> { inherent_impls: PerDefTable>, variances: PerDefTable>, generics: PerDefTable>, - predicates: PerDefTable>>, - predicates_defined_on: PerDefTable>>, + explicit_predicates: PerDefTable>>, + inferred_outlives: PerDefTable, Span)]>>, super_predicates: PerDefTable>>, mir: PerDefTable>>, @@ -524,8 +524,8 @@ impl<'tcx> EncodeContext<'tcx> { inherent_impls: self.per_def.inherent_impls.encode(&mut self.opaque), variances: self.per_def.variances.encode(&mut self.opaque), generics: self.per_def.generics.encode(&mut self.opaque), - predicates: self.per_def.predicates.encode(&mut self.opaque), - predicates_defined_on: self.per_def.predicates_defined_on.encode(&mut self.opaque), + explicit_predicates: self.per_def.explicit_predicates.encode(&mut self.opaque), + inferred_outlives: self.per_def.inferred_outlives.encode(&mut self.opaque), super_predicates: self.per_def.super_predicates.encode(&mut self.opaque), mir: self.per_def.mir.encode(&mut self.opaque), @@ -675,7 +675,8 @@ impl EncodeContext<'tcx> { self.encode_variances_of(def_id); } self.encode_generics(def_id); - self.encode_predicates(def_id); + self.encode_explicit_predicates(def_id); + self.encode_inferred_outlives(def_id); self.encode_optimized_mir(def_id); self.encode_promoted_mir(def_id); } @@ -718,7 +719,8 @@ impl EncodeContext<'tcx> { self.encode_variances_of(def_id); } self.encode_generics(def_id); - self.encode_predicates(def_id); + self.encode_explicit_predicates(def_id); + self.encode_inferred_outlives(def_id); self.encode_optimized_mir(def_id); self.encode_promoted_mir(def_id); } @@ -776,7 +778,8 @@ impl EncodeContext<'tcx> { self.encode_deprecation(def_id); self.encode_item_type(def_id); self.encode_generics(def_id); - self.encode_predicates(def_id); + self.encode_explicit_predicates(def_id); + self.encode_inferred_outlives(def_id); } fn encode_struct_ctor(&mut self, adt_def_id: DefId, def_id: DefId) { @@ -819,7 +822,8 @@ impl EncodeContext<'tcx> { self.encode_variances_of(def_id); } self.encode_generics(def_id); - self.encode_predicates(def_id); + self.encode_explicit_predicates(def_id); + self.encode_inferred_outlives(def_id); self.encode_optimized_mir(def_id); self.encode_promoted_mir(def_id); } @@ -829,15 +833,18 @@ impl EncodeContext<'tcx> { record!(self.per_def.generics[def_id] <- self.tcx.generics_of(def_id)); } - fn encode_predicates(&mut self, def_id: DefId) { - debug!("EncodeContext::encode_predicates({:?})", def_id); - record!(self.per_def.predicates[def_id] <- self.tcx.predicates_of(def_id)); + fn encode_explicit_predicates(&mut self, def_id: DefId) { + debug!("EncodeContext::encode_explicit_predicates({:?})", def_id); + record!(self.per_def.explicit_predicates[def_id] <- + self.tcx.explicit_predicates_of(def_id)); } - fn encode_predicates_defined_on(&mut self, def_id: DefId) { - debug!("EncodeContext::encode_predicates_defined_on({:?})", def_id); - record!(self.per_def.predicates_defined_on[def_id] <- - self.tcx.predicates_defined_on(def_id)) + fn encode_inferred_outlives(&mut self, def_id: DefId) { + debug!("EncodeContext::encode_inferred_outlives({:?})", def_id); + let inferred_outlives = self.tcx.inferred_outlives_of(def_id); + if !inferred_outlives.is_empty() { + record!(self.per_def.inferred_outlives[def_id] <- inferred_outlives); + } } fn encode_super_predicates(&mut self, def_id: DefId) { @@ -919,7 +926,8 @@ impl EncodeContext<'tcx> { self.encode_variances_of(def_id); } self.encode_generics(def_id); - self.encode_predicates(def_id); + self.encode_explicit_predicates(def_id); + self.encode_inferred_outlives(def_id); self.encode_optimized_mir(def_id); self.encode_promoted_mir(def_id); } @@ -986,7 +994,8 @@ impl EncodeContext<'tcx> { self.encode_variances_of(def_id); } self.encode_generics(def_id); - self.encode_predicates(def_id); + self.encode_explicit_predicates(def_id); + self.encode_inferred_outlives(def_id); let mir = match ast_item.kind { hir::ImplItemKind::Const(..) => true, hir::ImplItemKind::Method(ref sig, _) => { @@ -1260,22 +1269,11 @@ impl EncodeContext<'tcx> { hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => { self.encode_generics(def_id); - self.encode_predicates(def_id); + self.encode_explicit_predicates(def_id); + self.encode_inferred_outlives(def_id); } _ => {} } - // The only time that `predicates_defined_on` is used (on - // an external item) is for traits, during chalk lowering, - // so only encode it in that case as an efficiency - // hack. (No reason not to expand it in the future if - // necessary.) - match item.kind { - hir::ItemKind::Trait(..) | - hir::ItemKind::TraitAlias(..) => { - self.encode_predicates_defined_on(def_id); - } - _ => {} // not *wrong* for other kinds of items, but not needed - } match item.kind { hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => { @@ -1377,7 +1375,8 @@ impl EncodeContext<'tcx> { record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); self.encode_item_type(def_id); self.encode_generics(def_id); - self.encode_predicates(def_id); + self.encode_explicit_predicates(def_id); + self.encode_inferred_outlives(def_id); self.encode_optimized_mir(def_id); self.encode_promoted_mir(def_id); } @@ -1588,7 +1587,8 @@ impl EncodeContext<'tcx> { self.encode_variances_of(def_id); } self.encode_generics(def_id); - self.encode_predicates(def_id); + self.encode_explicit_predicates(def_id); + self.encode_inferred_outlives(def_id); } } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 8bece2511166e..f644b7264320b 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -244,8 +244,13 @@ crate struct LazyPerDefTables<'tcx> { pub inherent_impls: Lazy!(PerDefTable>), pub variances: Lazy!(PerDefTable>), pub generics: Lazy!(PerDefTable>), - pub predicates: Lazy!(PerDefTable)>), - pub predicates_defined_on: Lazy!(PerDefTable)>), + pub explicit_predicates: Lazy!(PerDefTable)>), + // FIXME(eddyb) this would ideally be `Lazy<[...]>` but `ty::Predicate` + // doesn't handle shorthands in its own (de)serialization impls, + // as it's an `enum` for which we want to derive (de)serialization, + // so the `ty::codec` APIs handle the whole `&'tcx [...]` at once. + // Also, as an optimization, a missing entry indicates an empty `&[]`. + pub inferred_outlives: Lazy!(PerDefTable, Span)])>), pub super_predicates: Lazy!(PerDefTable)>), pub mir: Lazy!(PerDefTable)>), diff --git a/src/librustc_mir/hair/constant.rs b/src/librustc_mir/hair/constant.rs index 956716f8ceaf7..b9e75a576cad8 100644 --- a/src/librustc_mir/hair/constant.rs +++ b/src/librustc_mir/hair/constant.rs @@ -45,10 +45,7 @@ crate fn lit_to_const<'tcx>( trunc(n as u128)? }, LitKind::Int(n, _) => trunc(n)?, - LitKind::Float(n, fty) => { - parse_float(n, fty, neg).map_err(|_| LitToConstError::UnparseableFloat)? - } - LitKind::FloatUnsuffixed(n) => { + LitKind::Float(n, _) => { let fty = match ty.kind { ty::Float(fty) => fty, _ => bug!() diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 1ecc78ba227ce..477ad10460f6b 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -293,10 +293,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> { match self.ty.kind { ty::Adt(def, _) if def.is_box() => write!(f, "box ")?, ty::Ref(_, _, mutbl) => { - write!(f, "&")?; - if mutbl == hir::MutMutable { - write!(f, "mut ")?; - } + write!(f, "&{}", mutbl.prefix_str())?; } _ => bug!("{} is a bad Deref pattern type", self.ty) } diff --git a/src/librustc_save_analysis/Cargo.toml b/src/librustc_save_analysis/Cargo.toml index b89c83d630b7d..2d93585e50ee4 100644 --- a/src/librustc_save_analysis/Cargo.toml +++ b/src/librustc_save_analysis/Cargo.toml @@ -13,7 +13,6 @@ log = "0.4" rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_codegen_utils = { path = "../librustc_codegen_utils" } -rustc_target = { path = "../librustc_target" } serde_json = "1" syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 203bd4d4167e2..019e92717b5d6 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -32,7 +32,7 @@ use rls_data::{SigElement, Signature}; use rustc::hir::def::{Res, DefKind}; use syntax::ast::{self, NodeId}; use syntax::print::pprust; - +use syntax_pos::sym; pub fn item_signature(item: &ast::Item, scx: &SaveContext<'_, '_>) -> Option { if !scx.config.signatures { @@ -157,6 +157,12 @@ fn text_sig(text: String) -> Signature { } } +fn push_abi(text: &mut String, abi: ast::Abi) { + if abi.symbol != sym::Rust { + text.push_str(&format!("extern \"{}\" ", abi.symbol)); + } +} + impl Sig for ast::Ty { fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext<'_, '_>) -> Result { let id = Some(self.id); @@ -231,11 +237,7 @@ impl Sig for ast::Ty { if f.unsafety == ast::Unsafety::Unsafe { text.push_str("unsafe "); } - if f.abi != rustc_target::spec::abi::Abi::Rust { - text.push_str("extern"); - text.push_str(&f.abi.to_string()); - text.push(' '); - } + push_abi(&mut text, f.abi); text.push_str("fn("); let mut defs = vec![]; @@ -385,11 +387,7 @@ impl Sig for ast::Item { if header.unsafety == ast::Unsafety::Unsafe { text.push_str("unsafe "); } - if header.abi != rustc_target::spec::abi::Abi::Rust { - text.push_str("extern"); - text.push_str(&header.abi.to_string()); - text.push(' '); - } + push_abi(&mut text, header.abi); text.push_str("fn "); let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?; @@ -948,11 +946,7 @@ fn make_method_signature( if m.header.unsafety == ast::Unsafety::Unsafe { text.push_str("unsafe "); } - if m.header.abi != rustc_target::spec::abi::Abi::Rust { - text.push_str("extern"); - text.push_str(&m.header.abi.to_string()); - text.push(' '); - } + push_abi(&mut text, m.header.abi); text.push_str("fn "); let mut sig = name_and_generics(text, 0, generics, id, ident, scx)?; diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index fde5c5bed4d91..e58caed0c99dd 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -3,11 +3,9 @@ pub use Primitive::*; use crate::spec::Target; -use std::fmt; use std::ops::{Add, Deref, Sub, Mul, AddAssign, Range, RangeInclusive}; use rustc_index::vec::{Idx, IndexVec}; -use syntax_pos::symbol::{sym, Symbol}; use syntax_pos::Span; pub mod call; @@ -534,49 +532,13 @@ impl Integer { } } - #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy, - PartialOrd, Ord)] + PartialOrd, Ord, Debug)] pub enum FloatTy { F32, F64, } -impl fmt::Debug for FloatTy { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self, f) - } -} - -impl fmt::Display for FloatTy { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.ty_to_string()) - } -} - -impl FloatTy { - pub fn ty_to_string(self) -> &'static str { - match self { - FloatTy::F32 => "f32", - FloatTy::F64 => "f64", - } - } - - pub fn to_symbol(self) -> Symbol { - match self { - FloatTy::F32 => sym::f32, - FloatTy::F64 => sym::f64, - } - } - - pub fn bit_width(self) -> usize { - match self { - FloatTy::F32 => 32, - FloatTy::F64 => 64, - } - } -} - /// Fundamental unit of memory access and layout. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub enum Primitive { diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 9cbde276ae97c..ded655c1ae32a 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -341,10 +341,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { tstr); match self.expr_ty.kind { ty::Ref(_, _, mt) => { - let mtstr = match mt { - hir::MutMutable => "mut ", - hir::MutImmutable => "", - }; + let mtstr = mt.prefix_str(); if self.cast_ty.is_trait() { match fcx.tcx.sess.source_map().span_to_snippet(self.cast_span) { Ok(s) => { diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 35870abbaefbd..bc1189e443e28 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -592,20 +592,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { cause.span, target_id, ); - let val = match ty.kind { - ty::Bool => "true", - ty::Char => "'a'", - ty::Int(_) | ty::Uint(_) => "42", - ty::Float(_) => "3.14159", - ty::Error | ty::Never => return, - _ => "value", - }; - let msg = "give it a value of the expected type"; - let label = destination.label - .map(|l| format!(" {}", l.ident)) - .unwrap_or_else(String::new); - let sugg = format!("break{} {}", label, val); - err.span_suggestion(expr.span, msg, sugg, Applicability::HasPlaceholders); + if let Some(val) = ty_kind_suggestion(ty) { + let label = destination.label + .map(|l| format!(" {}", l.ident)) + .unwrap_or_else(String::new); + err.span_suggestion( + expr.span, + "give it a value of the expected type", + format!("break{} {}", label, val), + Applicability::HasPlaceholders, + ); + } }, false); } } else { @@ -1725,3 +1722,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.mk_unit() } } + +pub(super) fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> { + Some(match ty.kind { + ty::Bool => "true", + ty::Char => "'a'", + ty::Int(_) | ty::Uint(_) => "42", + ty::Float(_) => "3.14159", + ty::Error | ty::Never => return None, + _ => "value", + }) +} diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 26f040810462f..fe2c7a200d202 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -127,7 +127,7 @@ use syntax::ast; use syntax::attr; use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax::source_map::{DUMMY_SP, original_sp}; -use syntax::symbol::{kw, sym}; +use syntax::symbol::{kw, sym, Ident}; use syntax::util::parser::ExprPrecedence; use std::cell::{Cell, RefCell, Ref, RefMut}; @@ -1800,12 +1800,12 @@ fn check_specialization_validity<'tcx>( fn check_impl_items_against_trait<'tcx>( tcx: TyCtxt<'tcx>, - impl_span: Span, + full_impl_span: Span, impl_id: DefId, impl_trait_ref: ty::TraitRef<'tcx>, impl_item_refs: &[hir::ImplItemRef], ) { - let impl_span = tcx.sess.source_map().def_span(impl_span); + let impl_span = tcx.sess.source_map().def_span(full_impl_span); // If the trait reference itself is erroneous (so the compilation is going // to fail), skip checking the items here -- the `impl_item` table in `tcx` @@ -1925,35 +1925,132 @@ fn check_impl_items_against_trait<'tcx>( } if !missing_items.is_empty() { - let mut err = struct_span_err!(tcx.sess, impl_span, E0046, - "not all trait items implemented, missing: `{}`", - missing_items.iter() - .map(|trait_item| trait_item.ident.to_string()) - .collect::>().join("`, `")); - err.span_label(impl_span, format!("missing `{}` in implementation", - missing_items.iter() - .map(|trait_item| trait_item.ident.to_string()) - .collect::>().join("`, `"))); - for trait_item in missing_items { - if let Some(span) = tcx.hir().span_if_local(trait_item.def_id) { - err.span_label(span, format!("`{}` from trait", trait_item.ident)); - } else { - err.note_trait_signature(trait_item.ident.to_string(), - trait_item.signature(tcx)); - } - } - err.emit(); + missing_items_err(tcx, impl_span, &missing_items, full_impl_span); } if !invalidated_items.is_empty() { let invalidator = overridden_associated_type.unwrap(); - span_err!(tcx.sess, invalidator.span, E0399, - "the following trait items need to be reimplemented \ - as `{}` was overridden: `{}`", - invalidator.ident, - invalidated_items.iter() - .map(|name| name.to_string()) - .collect::>().join("`, `")) + span_err!( + tcx.sess, + invalidator.span, + E0399, + "the following trait items need to be reimplemented as `{}` was overridden: `{}`", + invalidator.ident, + invalidated_items.iter() + .map(|name| name.to_string()) + .collect::>().join("`, `") + ) + } +} + +fn missing_items_err( + tcx: TyCtxt<'_>, + impl_span: Span, + missing_items: &[ty::AssocItem], + full_impl_span: Span, +) { + let missing_items_msg = missing_items.iter() + .map(|trait_item| trait_item.ident.to_string()) + .collect::>().join("`, `"); + + let mut err = struct_span_err!( + tcx.sess, + impl_span, + E0046, + "not all trait items implemented, missing: `{}`", + missing_items_msg + ); + err.span_label(impl_span, format!("missing `{}` in implementation", missing_items_msg)); + + // `Span` before impl block closing brace. + let hi = full_impl_span.hi() - BytePos(1); + // Point at the place right before the closing brace of the relevant `impl` to suggest + // adding the associated item at the end of its body. + let sugg_sp = full_impl_span.with_lo(hi).with_hi(hi); + // Obtain the level of indentation ending in `sugg_sp`. + let indentation = tcx.sess.source_map().span_to_margin(sugg_sp).unwrap_or(0); + // Make the whitespace that will make the suggestion have the right indentation. + let padding: String = (0..indentation).map(|_| " ").collect(); + + for trait_item in missing_items { + let snippet = suggestion_signature(&trait_item, tcx); + let code = format!("{}{}\n{}", padding, snippet, padding); + let msg = format!("implement the missing item: `{}`", snippet); + let appl = Applicability::HasPlaceholders; + if let Some(span) = tcx.hir().span_if_local(trait_item.def_id) { + err.span_label(span, format!("`{}` from trait", trait_item.ident)); + err.tool_only_span_suggestion(sugg_sp, &msg, code, appl); + } else { + err.span_suggestion_hidden(sugg_sp, &msg, code, appl); + } + } + err.emit(); +} + +/// Return placeholder code for the given function. +fn fn_sig_suggestion(sig: &ty::FnSig<'_>, ident: Ident) -> String { + let args = sig.inputs() + .iter() + .map(|ty| Some(match ty.kind { + ty::Param(param) if param.name == kw::SelfUpper => "self".to_string(), + ty::Ref(reg, ref_ty, mutability) => { + let reg = match &format!("{}", reg)[..] { + "'_" | "" => String::new(), + reg => format!("{} ", reg), + }; + match ref_ty.kind { + ty::Param(param) if param.name == kw::SelfUpper => { + format!("&{}{}self", reg, mutability.prefix_str()) + } + _ => format!("_: {:?}", ty), + } + } + _ => format!("_: {:?}", ty), + })) + .chain(std::iter::once(if sig.c_variadic { + Some("...".to_string()) + } else { + None + })) + .filter_map(|arg| arg) + .collect::>() + .join(", "); + let output = sig.output(); + let output = if !output.is_unit() { + format!(" -> {:?}", output) + } else { + String::new() + }; + + let unsafety = sig.unsafety.prefix_str(); + // FIXME: this is not entirely correct, as the lifetimes from borrowed params will + // not be present in the `fn` definition, not will we account for renamed + // lifetimes between the `impl` and the `trait`, but this should be good enough to + // fill in a significant portion of the missing code, and other subsequent + // suggestions can help the user fix the code. + format!("{}fn {}({}){} {{ unimplemented!() }}", unsafety, ident, args, output) +} + +/// Return placeholder code for the given associated item. +/// Similar to `ty::AssocItem::suggestion`, but appropriate for use as the code snippet of a +/// structured suggestion. +fn suggestion_signature(assoc: &ty::AssocItem, tcx: TyCtxt<'_>) -> String { + match assoc.kind { + ty::AssocKind::Method => { + // We skip the binder here because the binder would deanonymize all + // late-bound regions, and we don't want method signatures to show up + // `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound + // regions just fine, showing `fn(&MyType)`. + fn_sig_suggestion(tcx.fn_sig(assoc.def_id).skip_binder(), assoc.ident) + } + ty::AssocKind::Type => format!("type {} = Type;", assoc.ident), + // FIXME(type_alias_impl_trait): we should print bounds here too. + ty::AssocKind::OpaqueTy => format!("type {} = Type;", assoc.ident), + ty::AssocKind::Const => { + let ty = tcx.type_of(assoc.def_id); + let val = expr::ty_kind_suggestion(ty).unwrap_or("value"); + format!("const {}: {:?} = {};", assoc.ident, ty, val) + } } } @@ -3660,8 +3757,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); opt_ty.unwrap_or_else(|| self.next_int_var()) } - ast::LitKind::Float(_, t) => tcx.mk_mach_float(t), - ast::LitKind::FloatUnsuffixed(_) => { + ast::LitKind::Float(_, ast::LitFloatType::Suffixed(t)) => tcx.mk_mach_float(t), + ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) => { let opt_ty = expected.to_option(self).and_then(|ty| { match ty.kind { ty::Float(_) => Some(ty), diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 71a7b52a27ba9..ef84f1cb20f51 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1146,10 +1146,6 @@ fn report_assoc_ty_on_inherent_impl(tcx: TyCtxt<'_>, span: Span) { ); } -fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { - checked_type_of(tcx, def_id, true).unwrap() -} - fn infer_placeholder_type( tcx: TyCtxt<'_>, def_id: DefId, @@ -1193,26 +1189,14 @@ fn infer_placeholder_type( ty } -/// Same as [`type_of`] but returns [`Option`] instead of failing. -/// -/// If you want to fail anyway, you can set the `fail` parameter to true, but in this case, -/// you'd better just call [`type_of`] directly. -pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option> { +fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { use rustc::hir::*; - let hir_id = match tcx.hir().as_local_hir_id(def_id) { - Some(hir_id) => hir_id, - None => { - if !fail { - return None; - } - bug!("invalid node"); - } - }; + let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); let icx = ItemCtxt::new(tcx, def_id); - Some(match tcx.hir().get(hir_id) { + match tcx.hir().get(hir_id) { Node::TraitItem(item) => match item.kind { TraitItemKind::Method(..) => { let substs = InternalSubsts::identity_for_item(tcx, def_id); @@ -1229,9 +1213,6 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option icx.to_ty(ty), TraitItemKind::Type(_, None) => { - if !fail { - return None; - } span_bug!(item.span, "associated type missing default"); } }, @@ -1325,9 +1306,6 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option { - if !fail { - return None; - } span_bug!( item.span, "compute_type_of_item: unexpected item type: {:?}", @@ -1365,7 +1343,7 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option { if gen.is_some() { - return Some(tcx.typeck_tables_of(def_id).node_type(hir_id)); + return tcx.typeck_tables_of(def_id).node_type(hir_id); } let substs = InternalSubsts::identity_for_item(tcx, def_id); @@ -1440,13 +1418,9 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option, def_id: DefId, fail: bool) -> Option tcx.generics_of(def_id), - Res::Err => return Some(tcx.types.err), - _ if !fail => return None, + Res::Err => return tcx.types.err, res => { tcx.sess.delay_span_bug( DUMMY_SP, @@ -1466,7 +1439,7 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option, def_id: DefId, fail: bool) -> Option, def_id: DefId, fail: bool) -> Option { - if !fail { - return None; - } tcx.sess.delay_span_bug( DUMMY_SP, &format!( @@ -1551,21 +1518,13 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option { - if !fail { - return None; - } - bug!("unexpected non-type Node::GenericParam: {:?}", x) - }, + x => bug!("unexpected non-type Node::GenericParam: {:?}", x), }, x => { - if !fail { - return None; - } bug!("unexpected sort of node in type_of_def_id(): {:?}", x); } - }) + } } fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { @@ -2075,10 +2034,7 @@ fn explicit_predicates_of( } } - let hir_id = match tcx.hir().as_local_hir_id(def_id) { - Some(hir_id) => hir_id, - None => return tcx.predicates_of(def_id), - }; + let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); let node = tcx.hir().get(hir_id); let mut is_trait = None; diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 9374113e1c950..a5a4cfa2babc0 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -109,8 +109,6 @@ use util::common::time; use std::iter; use astconv::{AstConv, Bounds}; -pub use collect::checked_type_of; - pub struct TypeAndSubsts<'tcx> { substs: SubstsRef<'tcx>, ty: Ty<'tcx>, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 32c8ca234a0c3..0c670e5e7179a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1492,12 +1492,13 @@ impl GenericParamDefKind { } } - pub fn get_type(&self, cx: &DocContext<'_>) -> Option { - match *self { - GenericParamDefKind::Type { did, .. } => { - rustc_typeck::checked_type_of(cx.tcx, did, false).map(|t| t.clean(cx)) - } - GenericParamDefKind::Const { ref ty, .. } => Some(ty.clone()), + // FIXME(eddyb) this either returns the default of a type parameter, or the + // type of a `const` parameter. It seems that the intention is to *visit* + // any embedded types, but `get_type` seems to be the wrong name for that. + pub fn get_type(&self) -> Option { + match self { + GenericParamDefKind::Type { default, .. } => default.clone(), + GenericParamDefKind::Const { ty, .. } => Some(ty.clone()), GenericParamDefKind::Lifetime => None, } } @@ -1523,8 +1524,8 @@ impl GenericParamDef { self.kind.is_type() } - pub fn get_type(&self, cx: &DocContext<'_>) -> Option { - self.kind.get_type(cx) + pub fn get_type(&self) -> Option { + self.kind.get_type() } pub fn get_bounds(&self) -> Option<&[GenericBound]> { @@ -1892,7 +1893,7 @@ fn get_real_types( if !x.is_type() { continue } - if let Some(ty) = x.get_type(cx) { + if let Some(ty) = x.get_type() { let adds = get_real_types(generics, &ty, cx, recurse + 1); if !adds.is_empty() { res.extend(adds); diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml index b1839cc05cd1f..3e17e7949ea99 100644 --- a/src/libsyntax/Cargo.toml +++ b/src/libsyntax/Cargo.toml @@ -20,5 +20,4 @@ errors = { path = "../librustc_errors", package = "rustc_errors" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_index = { path = "../librustc_index" } rustc_lexer = { path = "../librustc_lexer" } -rustc_target = { path = "../librustc_target" } smallvec = { version = "1.0", features = ["union", "may_dangle"] } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 2392b809150d4..67d1acbccfbe5 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -22,7 +22,6 @@ pub use GenericArgs::*; pub use UnsafeSource::*; pub use crate::util::parser::ExprPrecedence; -pub use rustc_target::abi::FloatTy; pub use syntax_pos::symbol::{Ident, Symbol as Name}; use crate::parse::token::{self, DelimToken}; @@ -38,7 +37,6 @@ use rustc_data_structures::sync::Lrc; use rustc_data_structures::thin_vec::ThinVec; use rustc_index::vec::Idx; use rustc_serialize::{self, Decoder, Encoder}; -use rustc_target::spec::abi::Abi; #[cfg(target_arch = "x86_64")] use rustc_data_structures::static_assert_size; @@ -1401,7 +1399,7 @@ pub struct Lit { // Clippy uses Hash and PartialEq /// Type of the integer literal based on provided suffix. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, PartialEq)] +#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)] pub enum LitIntType { /// e.g. `42_i32`. Signed(IntTy), @@ -1411,6 +1409,15 @@ pub enum LitIntType { Unsuffixed, } +/// Type of the float literal based on provided suffix. +#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)] +pub enum LitFloatType { + /// A float literal with a suffix (`1f32` or `1E10f32`). + Suffixed(FloatTy), + /// A float literal without a suffix (`1.0 or 1.0E10`). + Unsuffixed, +} + /// Literal kind. /// /// E.g., `"foo"`, `42`, `12.34`, or `bool`. @@ -1428,9 +1435,7 @@ pub enum LitKind { /// An integer literal (`1`). Int(u128, LitIntType), /// A float literal (`1f64` or `1E10f64`). - Float(Symbol, FloatTy), - /// A float literal without a suffix (`1.0 or 1.0E10`). - FloatUnsuffixed(Symbol), + Float(Symbol, LitFloatType), /// A boolean literal. Bool(bool), /// Placeholder for a literal that wasn't well-formed in some way. @@ -1457,7 +1462,7 @@ impl LitKind { /// Returns `true` if this is a numeric literal. pub fn is_numeric(&self) -> bool { match *self { - LitKind::Int(..) | LitKind::Float(..) | LitKind::FloatUnsuffixed(..) => true, + LitKind::Int(..) | LitKind::Float(..) => true, _ => false, } } @@ -1474,14 +1479,14 @@ impl LitKind { // suffixed variants LitKind::Int(_, LitIntType::Signed(..)) | LitKind::Int(_, LitIntType::Unsigned(..)) - | LitKind::Float(..) => true, + | LitKind::Float(_, LitFloatType::Suffixed(..)) => true, // unsuffixed variants LitKind::Str(..) | LitKind::ByteStr(..) | LitKind::Byte(..) | LitKind::Char(..) | LitKind::Int(_, LitIntType::Unsuffixed) - | LitKind::FloatUnsuffixed(..) + | LitKind::Float(_, LitFloatType::Unsuffixed) | LitKind::Bool(..) | LitKind::Err(..) => false, } @@ -1553,7 +1558,36 @@ pub enum ImplItemKind { Macro(Mac), } -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Copy)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)] +pub enum FloatTy { + F32, + F64, +} + +impl FloatTy { + pub fn name_str(self) -> &'static str { + match self { + FloatTy::F32 => "f32", + FloatTy::F64 => "f64", + } + } + + pub fn name(self) -> Symbol { + match self { + FloatTy::F32 => sym::f32, + FloatTy::F64 => sym::f64, + } + } + + pub fn bit_width(self) -> usize { + match self { + FloatTy::F32 => 32, + FloatTy::F64 => 64, + } + } +} + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)] pub enum IntTy { Isize, I8, @@ -1563,20 +1597,8 @@ pub enum IntTy { I128, } -impl fmt::Debug for IntTy { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self, f) - } -} - -impl fmt::Display for IntTy { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.ty_to_string()) - } -} - impl IntTy { - pub fn ty_to_string(&self) -> &'static str { + pub fn name_str(&self) -> &'static str { match *self { IntTy::Isize => "isize", IntTy::I8 => "i8", @@ -1587,7 +1609,7 @@ impl IntTy { } } - pub fn to_symbol(&self) -> Symbol { + pub fn name(&self) -> Symbol { match *self { IntTy::Isize => sym::isize, IntTy::I8 => sym::i8, @@ -1602,7 +1624,7 @@ impl IntTy { // Cast to a `u128` so we can correctly print `INT128_MIN`. All integral types // are parsed as `u128`, so we wouldn't want to print an extra negative // sign. - format!("{}{}", val as u128, self.ty_to_string()) + format!("{}{}", val as u128, self.name_str()) } pub fn bit_width(&self) -> Option { @@ -1617,7 +1639,7 @@ impl IntTy { } } -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Copy)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Copy, Debug)] pub enum UintTy { Usize, U8, @@ -1628,7 +1650,7 @@ pub enum UintTy { } impl UintTy { - pub fn ty_to_string(&self) -> &'static str { + pub fn name_str(&self) -> &'static str { match *self { UintTy::Usize => "usize", UintTy::U8 => "u8", @@ -1639,7 +1661,7 @@ impl UintTy { } } - pub fn to_symbol(&self) -> Symbol { + pub fn name(&self) -> Symbol { match *self { UintTy::Usize => sym::usize, UintTy::U8 => sym::u8, @@ -1651,7 +1673,7 @@ impl UintTy { } pub fn val_to_string(&self, val: u128) -> String { - format!("{}{}", val, self.ty_to_string()) + format!("{}{}", val, self.name_str()) } pub fn bit_width(&self) -> Option { @@ -1666,18 +1688,6 @@ impl UintTy { } } -impl fmt::Debug for UintTy { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self, f) - } -} - -impl fmt::Display for UintTy { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.ty_to_string()) - } -} - /// A constraint on an associated type (e.g., `A = Bar` in `Foo` or /// `A: TraitA + TraitB` in `Foo`). #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] @@ -2358,6 +2368,27 @@ impl Item { } } +/// A reference to an ABI. +/// +/// In AST our notion of an ABI is still syntactic unlike in `rustc_target::spec::abi::Abi`. +#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, PartialEq)] +pub struct Abi { + pub symbol: Symbol, + pub span: Span, +} + +impl Abi { + pub fn new(symbol: Symbol, span: Span) -> Self { + Self { symbol, span } + } +} + +impl Default for Abi { + fn default() -> Self { + Self::new(sym::Rust, DUMMY_SP) + } +} + /// A function header. /// /// All the information between the visibility and the name of the function is @@ -2376,7 +2407,7 @@ impl Default for FnHeader { unsafety: Unsafety::Normal, asyncness: dummy_spanned(IsAsync::NotAsync), constness: dummy_spanned(Constness::NotConst), - abi: Abi::Rust, + abi: Abi::default(), } } } diff --git a/src/libsyntax/error_codes.rs b/src/libsyntax/error_codes.rs index 941df5ea57087..c23c8d65a7f23 100644 --- a/src/libsyntax/error_codes.rs +++ b/src/libsyntax/error_codes.rs @@ -540,6 +540,5 @@ equivalent in Rust would be to use macros directly. E0630, E0693, // incorrect `repr(align)` attribute format // E0694, // an unknown tool name found in scoped attributes - E0703, // invalid ABI E0717, // rustc_promotable without stability attribute } diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index b7e75ff3a7e38..5b1493ebc9b01 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -18,7 +18,6 @@ use crate::tokenstream::TokenTree; use errors::{Applicability, DiagnosticBuilder, Handler}; use rustc_data_structures::fx::FxHashMap; -use rustc_target::spec::abi::Abi; use syntax_pos::{Span, DUMMY_SP, MultiSpan}; use log::debug; @@ -192,62 +191,70 @@ macro_rules! gate_feature_post { } impl<'a> PostExpansionVisitor<'a> { - fn check_abi(&self, abi: Abi, span: Span) { - match abi { - Abi::RustIntrinsic => { + fn check_abi(&self, abi: ast::Abi) { + let ast::Abi { symbol, span } = abi; + + match &*symbol.as_str() { + // Stable + "Rust" | + "C" | + "cdecl" | + "stdcall" | + "fastcall" | + "aapcs" | + "win64" | + "sysv64" | + "system" => {} + "rust-intrinsic" => { gate_feature_post!(&self, intrinsics, span, "intrinsics are subject to change"); }, - Abi::PlatformIntrinsic => { + "platform-intrinsic" => { gate_feature_post!(&self, platform_intrinsics, span, "platform intrinsics are experimental and possibly buggy"); }, - Abi::Vectorcall => { + "vectorcall" => { gate_feature_post!(&self, abi_vectorcall, span, "vectorcall is experimental and subject to change"); }, - Abi::Thiscall => { + "thiscall" => { gate_feature_post!(&self, abi_thiscall, span, "thiscall is experimental and subject to change"); }, - Abi::RustCall => { + "rust-call" => { gate_feature_post!(&self, unboxed_closures, span, "rust-call ABI is subject to change"); }, - Abi::PtxKernel => { + "ptx-kernel" => { gate_feature_post!(&self, abi_ptx, span, "PTX ABIs are experimental and subject to change"); }, - Abi::Unadjusted => { + "unadjusted" => { gate_feature_post!(&self, abi_unadjusted, span, "unadjusted ABI is an implementation detail and perma-unstable"); }, - Abi::Msp430Interrupt => { + "msp430-interrupt" => { gate_feature_post!(&self, abi_msp430_interrupt, span, "msp430-interrupt ABI is experimental and subject to change"); }, - Abi::X86Interrupt => { + "x86-interrupt" => { gate_feature_post!(&self, abi_x86_interrupt, span, "x86-interrupt ABI is experimental and subject to change"); }, - Abi::AmdGpuKernel => { + "amdgpu-kernel" => { gate_feature_post!(&self, abi_amdgpu_kernel, span, "amdgpu-kernel ABI is experimental and subject to change"); }, - Abi::EfiApi => { + "efiapi" => { gate_feature_post!(&self, abi_efiapi, span, "efiapi ABI is experimental and subject to change"); }, - // Stable - Abi::Cdecl | - Abi::Stdcall | - Abi::Fastcall | - Abi::Aapcs | - Abi::Win64 | - Abi::SysV64 | - Abi::Rust | - Abi::C | - Abi::System => {} + abi => { + self.parse_sess.span_diagnostic.delay_span_bug( + span, + &format!("unrecognized ABI not caught in lowering: {}", abi), + ) + } } } @@ -373,7 +380,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_item(&mut self, i: &'a ast::Item) { match i.kind { ast::ItemKind::ForeignMod(ref foreign_module) => { - self.check_abi(foreign_module.abi, i.span); + self.check_abi(foreign_module.abi); } ast::ItemKind::Fn(..) => { @@ -503,7 +510,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_ty(&mut self, ty: &'a ast::Ty) { match ty.kind { ast::TyKind::BareFn(ref bare_fn_ty) => { - self.check_abi(bare_fn_ty.abi, ty.span); + self.check_abi(bare_fn_ty.abi); } ast::TyKind::Never => { gate_feature_post!(&self, never_type, ty.span, @@ -597,7 +604,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { // Stability of const fn methods are covered in // `visit_trait_item` and `visit_impl_item` below; this is // because default methods don't pass through this point. - self.check_abi(header.abi, span); + self.check_abi(header.abi); } if fn_decl.c_variadic() { @@ -631,7 +638,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { match ti.kind { ast::TraitItemKind::Method(ref sig, ref block) => { if block.is_none() { - self.check_abi(sig.header.abi, ti.span); + self.check_abi(sig.header.abi); } if sig.decl.c_variadic() { gate_feature_post!(&self, c_variadic, ti.span, @@ -863,18 +870,17 @@ pub fn check_crate(krate: &ast::Crate, maybe_stage_features(&parse_sess.span_diagnostic, krate, unstable); let mut visitor = PostExpansionVisitor { parse_sess, features }; + let spans = parse_sess.gated_spans.spans.borrow(); macro_rules! gate_all { - ($gate:ident, $msg:literal) => { gate_all!($gate, $gate, $msg); }; - ($spans:ident, $gate:ident, $msg:literal) => { - for span in &*parse_sess.gated_spans.$spans.borrow() { + ($gate:ident, $msg:literal) => { + for span in spans.get(&sym::$gate).unwrap_or(&vec![]) { gate_feature!(&visitor, $gate, *span, $msg); } } } - gate_all!(let_chains, "`let` expressions in this position are experimental"); gate_all!(async_closure, "async closures are unstable"); - gate_all!(yields, generators, "yield syntax is experimental"); + gate_all!(generators, "yield syntax is experimental"); gate_all!(or_patterns, "or-patterns syntax is experimental"); gate_all!(const_extern_fn, "`const extern fn` definitions are unstable"); @@ -885,7 +891,7 @@ pub fn check_crate(krate: &ast::Crate, // FIXME(eddyb) do something more useful than always // disabling these uses of early feature-gatings. if false { - for span in &*parse_sess.gated_spans.$gate.borrow() { + for span in spans.get(&sym::$gate).unwrap_or(&vec![]) { gate_feature!(&visitor, $gate, *span, $msg); } } @@ -902,7 +908,6 @@ pub fn check_crate(krate: &ast::Crate, gate_all!(try_blocks, "`try` blocks are unstable"); gate_all!(label_break_value, "labels on blocks are unstable"); gate_all!(box_syntax, "box expression syntax is experimental; you can call `Box::new` instead"); - // To avoid noise about type ascription in common syntax errors, // only emit if it is the *only* error. (Also check it last.) if parse_sess.span_diagnostic.err_count() == 0 { diff --git a/src/libsyntax/parse/literal.rs b/src/libsyntax/parse/literal.rs index c42f4aa25cc96..a8eeac59954f1 100644 --- a/src/libsyntax/parse/literal.rs +++ b/src/libsyntax/parse/literal.rs @@ -157,17 +157,18 @@ impl LitKind { } LitKind::Int(n, ty) => { let suffix = match ty { - ast::LitIntType::Unsigned(ty) => Some(ty.to_symbol()), - ast::LitIntType::Signed(ty) => Some(ty.to_symbol()), + ast::LitIntType::Unsigned(ty) => Some(ty.name()), + ast::LitIntType::Signed(ty) => Some(ty.name()), ast::LitIntType::Unsuffixed => None, }; (token::Integer, sym::integer(n), suffix) } LitKind::Float(symbol, ty) => { - (token::Float, symbol, Some(ty.to_symbol())) - } - LitKind::FloatUnsuffixed(symbol) => { - (token::Float, symbol, None) + let suffix = match ty { + ast::LitFloatType::Suffixed(ty) => Some(ty.name()), + ast::LitFloatType::Unsuffixed => None, + }; + (token::Float, symbol, suffix) } LitKind::Bool(value) => { let symbol = if value { kw::True } else { kw::False }; @@ -244,12 +245,12 @@ fn filtered_float_lit(symbol: Symbol, suffix: Option, base: u32) return Err(LitError::NonDecimalFloat(base)); } Ok(match suffix { - Some(suf) => match suf { - sym::f32 => LitKind::Float(symbol, ast::FloatTy::F32), - sym::f64 => LitKind::Float(symbol, ast::FloatTy::F64), + Some(suf) => LitKind::Float(symbol, ast::LitFloatType::Suffixed(match suf { + sym::f32 => ast::FloatTy::F32, + sym::f64 => ast::FloatTy::F64, _ => return Err(LitError::InvalidFloatSuffix), - } - None => LitKind::FloatUnsuffixed(symbol) + })), + None => LitKind::Float(symbol, ast::LitFloatType::Unsuffixed) }) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 7652c730e51b6..1284e89f195c7 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -12,7 +12,7 @@ mod diagnostics; use diagnostics::Error; use crate::ast::{ - self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Ident, + self, Abi, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Ident, IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety, }; use crate::parse::{PResult, Directory, DirectoryOwnership}; @@ -28,7 +28,6 @@ use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint}; use crate::ThinVec; use errors::{Applicability, DiagnosticBuilder, DiagnosticId, FatalError}; -use rustc_target::spec::abi::{self, Abi}; use syntax_pos::{Span, BytePos, DUMMY_SP, FileName}; use log::debug; @@ -1121,7 +1120,7 @@ impl<'a> Parser<'a> { self.expected_tokens.push(TokenType::Keyword(kw::Crate)); if self.is_crate_vis() { self.bump(); // `crate` - self.sess.gated_spans.crate_visibility_modifier.borrow_mut().push(self.prev_span); + self.sess.gated_spans.gate(sym::crate_visibility_modifier, self.prev_span); return Ok(respan(self.prev_span, VisibilityKind::Crate(CrateSugar::JustCrate))); } @@ -1206,48 +1205,41 @@ impl<'a> Parser<'a> { Ok(()) } - /// Parses `extern` followed by an optional ABI string, or nothing. + /// Parses `extern string_literal?`. + /// If `extern` is not found, the Rust ABI is used. + /// If `extern` is found and a `string_literal` does not follow, the C ABI is used. fn parse_extern_abi(&mut self) -> PResult<'a, Abi> { - if self.eat_keyword(kw::Extern) { - Ok(self.parse_opt_abi()?.unwrap_or(Abi::C)) + Ok(if self.eat_keyword(kw::Extern) { + self.parse_opt_abi()? } else { - Ok(Abi::Rust) - } + Abi::default() + }) } - /// Parses a string as an ABI spec on an extern type or module. Consumes - /// the `extern` keyword, if one is found. - fn parse_opt_abi(&mut self) -> PResult<'a, Option> { - match self.token.kind { - token::Literal(token::Lit { kind: token::Str, symbol, suffix }) | - token::Literal(token::Lit { kind: token::StrRaw(..), symbol, suffix }) => { - self.expect_no_suffix(self.token.span, "an ABI spec", suffix); - self.bump(); - match abi::lookup(&symbol.as_str()) { - Some(abi) => Ok(Some(abi)), - None => { - self.error_on_invalid_abi(symbol); - Ok(None) - } + /// Parses a string literal as an ABI spec. + /// If one is not found, the "C" ABI is used. + fn parse_opt_abi(&mut self) -> PResult<'a, Abi> { + let span = if self.token.can_begin_literal_or_bool() { + let ast::Lit { span, kind, .. } = self.parse_lit()?; + match kind { + ast::LitKind::Str(symbol, _) => return Ok(Abi::new(symbol, span)), + ast::LitKind::Err(_) => {} + _ => { + self.struct_span_err(span, "non-string ABI literal") + .span_suggestion( + span, + "specify the ABI with a string literal", + "\"C\"".to_string(), + Applicability::MaybeIncorrect, + ) + .emit(); } } - _ => Ok(None), - } - } - - /// Emit an error where `symbol` is an invalid ABI. - fn error_on_invalid_abi(&self, symbol: Symbol) { - let prev_span = self.prev_span; - struct_span_err!( - self.sess.span_diagnostic, - prev_span, - E0703, - "invalid ABI: found `{}`", - symbol - ) - .span_label(prev_span, "invalid ABI") - .help(&format!("valid ABIs: {}", abi::all_names().join(", "))) - .emit(); + span + } else { + self.prev_span + }; + Ok(Abi::new(sym::C, span)) } /// We are parsing `async fn`. If we are on Rust 2015, emit an error. diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 97b1092452aaf..509e6482dcc06 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -16,10 +16,10 @@ use crate::parse::token::{self, Token, TokenKind}; use crate::print::pprust; use crate::ptr::P; use crate::source_map::{self, Span}; -use crate::symbol::{kw, sym}; use crate::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par}; use errors::Applicability; +use syntax_pos::symbol::{kw, sym}; use syntax_pos::Symbol; use std::mem; use rustc_data_structures::thin_vec::ThinVec; @@ -252,7 +252,7 @@ impl<'a> Parser<'a> { self.last_type_ascription = Some((self.prev_span, maybe_path)); lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type)?; - self.sess.gated_spans.type_ascription.borrow_mut().push(lhs.span); + self.sess.gated_spans.gate(sym::type_ascription, lhs.span); continue } else if op == AssocOp::DotDot || op == AssocOp::DotDotEq { // If we didn’t have to handle `x..`/`x..=`, it would be pretty easy to @@ -455,7 +455,7 @@ impl<'a> Parser<'a> { let e = self.parse_prefix_expr(None); let (span, e) = self.interpolated_or_expr_span(e)?; let span = lo.to(span); - self.sess.gated_spans.box_syntax.borrow_mut().push(span); + self.sess.gated_spans.gate(sym::box_syntax, span); (span, ExprKind::Box(e)) } token::Ident(..) if self.token.is_ident_named(sym::not) => { @@ -1045,7 +1045,7 @@ impl<'a> Parser<'a> { } let span = lo.to(hi); - self.sess.gated_spans.yields.borrow_mut().push(span); + self.sess.gated_spans.gate(sym::generators, span); } else if self.eat_keyword(kw::Let) { return self.parse_let_expr(attrs); } else if is_span_rust_2018 && self.eat_keyword(kw::Await) { @@ -1116,7 +1116,11 @@ impl<'a> Parser<'a> { Err(self.span_fatal(token.span, &msg)) } Err(err) => { - let (lit, span) = (token.expect_lit(), token.span); + let span = token.span; + let lit = match token.kind { + token::Literal(lit) => lit, + _ => unreachable!(), + }; self.bump(); self.error_literal_from_token(err, lit, span); // Pack possible quotes and prefixes from the original literal into @@ -1264,7 +1268,7 @@ impl<'a> Parser<'a> { outer_attrs: ThinVec, ) -> PResult<'a, P> { if let Some(label) = opt_label { - self.sess.gated_spans.label_break_value.borrow_mut().push(label.ident.span); + self.sess.gated_spans.gate(sym::label_break_value, label.ident.span); } self.expect(&token::OpenDelim(token::Brace))?; @@ -1293,7 +1297,7 @@ impl<'a> Parser<'a> { }; if asyncness.is_async() { // Feature-gate `async ||` closures. - self.sess.gated_spans.async_closure.borrow_mut().push(self.prev_span); + self.sess.gated_spans.gate(sym::async_closure, self.prev_span); } let capture_clause = self.parse_capture_clause(); @@ -1415,8 +1419,7 @@ impl<'a> Parser<'a> { if let ExprKind::Let(..) = cond.kind { // Remove the last feature gating of a `let` expression since it's stable. - let last = self.sess.gated_spans.let_chains.borrow_mut().pop(); - debug_assert_eq!(cond.span, last.unwrap()); + self.sess.gated_spans.ungate_last(sym::let_chains, cond.span); } Ok(cond) @@ -1433,7 +1436,7 @@ impl<'a> Parser<'a> { |this| this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into()) )?; let span = lo.to(expr.span); - self.sess.gated_spans.let_chains.borrow_mut().push(span); + self.sess.gated_spans.gate(sym::let_chains, span); Ok(self.mk_expr(span, ExprKind::Let(pat, expr), attrs)) } @@ -1654,7 +1657,7 @@ impl<'a> Parser<'a> { Err(error) } else { let span = span_lo.to(body.span); - self.sess.gated_spans.try_blocks.borrow_mut().push(span); + self.sess.gated_spans.gate(sym::try_blocks, span); Ok(self.mk_expr(span, ExprKind::TryBlock(body), attrs)) } } diff --git a/src/libsyntax/parse/parser/generics.rs b/src/libsyntax/parse/parser/generics.rs index 51caae69c86a4..3c094750b4d98 100644 --- a/src/libsyntax/parse/parser/generics.rs +++ b/src/libsyntax/parse/parser/generics.rs @@ -3,7 +3,8 @@ use super::{Parser, PResult}; use crate::ast::{self, WhereClause, GenericParam, GenericParamKind, GenericBounds, Attribute}; use crate::parse::token; use crate::source_map::DUMMY_SP; -use crate::symbol::kw; + +use syntax_pos::symbol::{kw, sym}; impl<'a> Parser<'a> { /// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`. @@ -62,7 +63,7 @@ impl<'a> Parser<'a> { self.expect(&token::Colon)?; let ty = self.parse_ty()?; - self.sess.gated_spans.const_generics.borrow_mut().push(lo.to(self.prev_span)); + self.sess.gated_spans.gate(sym::const_generics, lo.to(self.prev_span)); Ok(GenericParam { ident, diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index cc6235c6fc772..9d543055f23a7 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -3,7 +3,7 @@ use super::diagnostics::{Error, dummy_arg, ConsumeClosingDelim}; use crate::maybe_whole; use crate::ptr::P; -use crate::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item}; +use crate::ast::{self, Abi, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item}; use crate::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind}; use crate::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness}; use crate::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind}; @@ -17,7 +17,6 @@ use crate::ThinVec; use log::debug; use std::mem; -use rustc_target::spec::abi::Abi; use errors::{Applicability, DiagnosticBuilder, DiagnosticId, StashKey}; use syntax_pos::BytePos; @@ -111,7 +110,7 @@ impl<'a> Parser<'a> { return Ok(Some(self.parse_item_extern_crate(lo, vis, attrs)?)); } - let opt_abi = self.parse_opt_abi()?; + let abi = self.parse_opt_abi()?; if self.eat_keyword(kw::Fn) { // EXTERN FUNCTION ITEM @@ -120,12 +119,12 @@ impl<'a> Parser<'a> { unsafety: Unsafety::Normal, asyncness: respan(fn_span, IsAsync::NotAsync), constness: respan(fn_span, Constness::NotConst), - abi: opt_abi.unwrap_or(Abi::C), + abi, }; return self.parse_item_fn(lo, vis, attrs, header); } else if self.check(&token::OpenDelim(token::Brace)) { return Ok(Some( - self.parse_item_foreign_mod(lo, opt_abi, vis, attrs, extern_sp)?, + self.parse_item_foreign_mod(lo, abi, vis, attrs, extern_sp)?, )); } @@ -147,9 +146,7 @@ impl<'a> Parser<'a> { let unsafety = self.parse_unsafety(); if self.check_keyword(kw::Extern) { - self.sess.gated_spans.const_extern_fn.borrow_mut().push( - lo.to(self.token.span) - ); + self.sess.gated_spans.gate(sym::const_extern_fn, lo.to(self.token.span)); } let abi = self.parse_extern_abi()?; self.bump(); // `fn` @@ -201,7 +198,7 @@ impl<'a> Parser<'a> { unsafety, asyncness, constness: respan(fn_span, Constness::NotConst), - abi: Abi::Rust, + abi: Abi::new(sym::Rust, fn_span), }; return self.parse_item_fn(lo, vis, attrs, header); } @@ -238,7 +235,7 @@ impl<'a> Parser<'a> { unsafety: Unsafety::Normal, asyncness: respan(fn_span, IsAsync::NotAsync), constness: respan(fn_span, Constness::NotConst), - abi: Abi::Rust, + abi: Abi::new(sym::Rust, fn_span), }; return self.parse_item_fn(lo, vis, attrs, header); } @@ -832,7 +829,7 @@ impl<'a> Parser<'a> { .emit(); } - self.sess.gated_spans.trait_alias.borrow_mut().push(whole_span); + self.sess.gated_spans.gate(sym::trait_alias, whole_span); Ok((ident, ItemKind::TraitAlias(tps, bounds), None)) } else { @@ -1115,15 +1112,13 @@ impl<'a> Parser<'a> { fn parse_item_foreign_mod( &mut self, lo: Span, - opt_abi: Option, + abi: Abi, visibility: Visibility, mut attrs: Vec, extern_sp: Span, ) -> PResult<'a, P> { self.expect(&token::OpenDelim(token::Brace))?; - let abi = opt_abi.unwrap_or(Abi::C); - attrs.extend(self.parse_inner_attributes()?); let mut foreign_items = vec![]; @@ -1714,7 +1709,7 @@ impl<'a> Parser<'a> { let span = lo.to(self.prev_span); if !def.legacy { - self.sess.gated_spans.decl_macro.borrow_mut().push(span); + self.sess.gated_spans.gate(sym::decl_macro, span); } Ok(Some(self.mk_item(span, ident, ItemKind::MacroDef(def), vis.clone(), attrs.to_vec()))) @@ -1801,7 +1796,7 @@ impl<'a> Parser<'a> { ) -> PResult<'a, Option>> { let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { is_self_allowed: false, - allow_c_variadic: header.abi == Abi::C && header.unsafety == Unsafety::Unsafe, + allow_c_variadic: header.abi.symbol == sym::C && header.unsafety == Unsafety::Unsafe, is_name_required: |_| true, })?; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; @@ -1930,7 +1925,7 @@ impl<'a> Parser<'a> { let asyncness = respan(self.prev_span, asyncness); let unsafety = self.parse_unsafety(); let (constness, unsafety, abi) = if is_const_fn { - (respan(const_span, Constness::Const), unsafety, Abi::Rust) + (respan(const_span, Constness::Const), unsafety, Abi::default()) } else { let abi = self.parse_extern_abi()?; (respan(self.prev_span, Constness::NotConst), unsafety, abi) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 969d5dd837480..cc8738edff7f5 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -8,9 +8,8 @@ use crate::mut_visit::{noop_visit_pat, noop_visit_mac, MutVisitor}; use crate::parse::token::{self}; use crate::print::pprust; use crate::source_map::{respan, Span, Spanned}; -use crate::symbol::kw; use crate::ThinVec; - +use syntax_pos::symbol::{kw, sym}; use errors::{Applicability, DiagnosticBuilder}; type Expected = Option<&'static str>; @@ -52,11 +51,8 @@ impl<'a> Parser<'a> { // and no other gated or-pattern has been parsed thus far, // then we should really gate the leading `|`. // This complicated procedure is done purely for diagnostics UX. - if gated_leading_vert { - let mut or_pattern_spans = self.sess.gated_spans.or_patterns.borrow_mut(); - if or_pattern_spans.is_empty() { - or_pattern_spans.push(leading_vert_span); - } + if gated_leading_vert && self.sess.gated_spans.is_ungated(sym::or_patterns) { + self.sess.gated_spans.gate(sym::or_patterns, leading_vert_span); } Ok(pat) @@ -117,7 +113,7 @@ impl<'a> Parser<'a> { // Feature gate the or-pattern if instructed: if gate_or == GateOr::Yes { - self.sess.gated_spans.or_patterns.borrow_mut().push(or_pattern_span); + self.sess.gated_spans.gate(sym::or_patterns, or_pattern_span); } Ok(self.mk_pat(or_pattern_span, PatKind::Or(pats))) @@ -325,7 +321,7 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(kw::Box) { // Parse `box pat` let pat = self.parse_pat_with_range_pat(false, None)?; - self.sess.gated_spans.box_patterns.borrow_mut().push(lo.to(self.prev_span)); + self.sess.gated_spans.gate(sym::box_patterns, lo.to(self.prev_span)); PatKind::Box(pat) } else if self.can_be_ident_pat() { // Parse `ident @ pat` @@ -612,7 +608,7 @@ impl<'a> Parser<'a> { } fn excluded_range_end(&self, span: Span) -> RangeEnd { - self.sess.gated_spans.exclusive_range_pattern.borrow_mut().push(span); + self.sess.gated_spans.gate(sym::exclusive_range_pattern, span); RangeEnd::Excluded } diff --git a/src/libsyntax/parse/parser/path.rs b/src/libsyntax/parse/parser/path.rs index f9944e36e2f60..4438d61d9eedd 100644 --- a/src/libsyntax/parse/parser/path.rs +++ b/src/libsyntax/parse/parser/path.rs @@ -5,7 +5,7 @@ use crate::ast::{self, QSelf, Path, PathSegment, Ident, ParenthesizedArgs, Angle use crate::ast::{AnonConst, GenericArg, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode}; use crate::parse::token::{self, Token}; use crate::source_map::{Span, BytePos}; -use crate::symbol::kw; +use syntax_pos::symbol::{kw, sym}; use std::mem; use log::debug; @@ -426,7 +426,7 @@ impl<'a> Parser<'a> { // Gate associated type bounds, e.g., `Iterator`. if let AssocTyConstraintKind::Bound { .. } = kind { - self.sess.gated_spans.associated_type_bounds.borrow_mut().push(span); + self.sess.gated_spans.gate(sym::associated_type_bounds, span); } constraints.push(AssocTyConstraint { diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 03e77b199cc3b..6f3da344ccf88 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -381,9 +381,7 @@ impl Token { match self.kind { OpenDelim(Brace) => true, Interpolated(ref nt) => match **nt { - NtExpr(..) => true, - NtBlock(..) => true, - NtLiteral(..) => true, + NtExpr(..) | NtBlock(..) | NtLiteral(..) => true, _ => false, } _ => self.can_begin_literal_or_bool(), @@ -404,13 +402,6 @@ impl Token { } } - crate fn expect_lit(&self) -> Lit { - match self.kind { - Literal(lit) => lit, - _ => panic!("`expect_lit` called on non-literal"), - } - } - /// Returns `true` if the token is any literal, a minus (which can prefix a literal, /// for example a '-42', or one of the boolean idents). pub fn can_begin_literal_or_bool(&self) -> bool { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index c8afe8a1ff459..1d59c13a9d081 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -14,7 +14,6 @@ use crate::sess::ParseSess; use crate::symbol::{kw, sym}; use crate::tokenstream::{self, TokenStream, TokenTree}; -use rustc_target::spec::abi::{self, Abi}; use syntax_pos::{self, BytePos}; use syntax_pos::{FileName, Span}; @@ -1230,7 +1229,7 @@ impl<'a> State<'a> { } ast::ItemKind::ForeignMod(ref nmod) => { self.head("extern"); - self.word_nbsp(nmod.abi.to_string()); + self.print_abi(nmod.abi); self.bopen(); self.print_foreign_mod(nmod, &item.attrs); self.bclose(item.span); @@ -2823,7 +2822,7 @@ impl<'a> State<'a> { } crate fn print_ty_fn(&mut self, - abi: abi::Abi, + abi: ast::Abi, unsafety: ast::Unsafety, decl: &ast::FnDecl, name: Option, @@ -2884,14 +2883,18 @@ impl<'a> State<'a> { self.print_asyncness(header.asyncness.node); self.print_unsafety(header.unsafety); - if header.abi != Abi::Rust { + if header.abi.symbol != sym::Rust { self.word_nbsp("extern"); - self.word_nbsp(header.abi.to_string()); + self.print_abi(header.abi); } self.s.word("fn") } + fn print_abi(&mut self, abi: ast::Abi) { + self.word_nbsp(format!("\"{}\"", abi.symbol)); + } + crate fn print_unsafety(&mut self, s: ast::Unsafety) { match s { ast::Unsafety::Normal => {}, diff --git a/src/libsyntax/print/pprust/tests.rs b/src/libsyntax/print/pprust/tests.rs index faa70edbfa29b..2c6dd0fb1c6dc 100644 --- a/src/libsyntax/print/pprust/tests.rs +++ b/src/libsyntax/print/pprust/tests.rs @@ -34,12 +34,7 @@ fn test_fun_to_string() { assert_eq!( fun_to_string( &decl, - ast::FnHeader { - unsafety: ast::Unsafety::Normal, - constness: source_map::dummy_spanned(ast::Constness::NotConst), - asyncness: source_map::dummy_spanned(ast::IsAsync::NotAsync), - abi: Abi::Rust, - }, + ast::FnHeader::default(), abba_ident, &generics ), diff --git a/src/libsyntax/sess.rs b/src/libsyntax/sess.rs index 30f8c56a05619..faad3e4af1e46 100644 --- a/src/libsyntax/sess.rs +++ b/src/libsyntax/sess.rs @@ -19,39 +19,53 @@ use std::str; /// Collected spans during parsing for places where a certain feature was /// used and should be feature gated accordingly in `check_crate`. #[derive(Default)] -crate struct GatedSpans { - /// Spans collected for gating `let_chains`, e.g. `if a && let b = c {}`. - crate let_chains: Lock>, - /// Spans collected for gating `async_closure`, e.g. `async || ..`. - crate async_closure: Lock>, - /// Spans collected for gating `yield e?` expressions (`generators` gate). - crate yields: Lock>, - /// Spans collected for gating `or_patterns`, e.g. `Some(Foo | Bar)`. - crate or_patterns: Lock>, - /// Spans collected for gating `const_extern_fn`, e.g. `const extern fn foo`. - crate const_extern_fn: Lock>, - /// Spans collected for gating `trait_alias`, e.g. `trait Foo = Ord + Eq;`. - pub trait_alias: Lock>, - /// Spans collected for gating `associated_type_bounds`, e.g. `Iterator`. - pub associated_type_bounds: Lock>, - /// Spans collected for gating `crate_visibility_modifier`, e.g. `crate fn`. - pub crate_visibility_modifier: Lock>, - /// Spans collected for gating `const_generics`, e.g. `const N: usize`. - pub const_generics: Lock>, - /// Spans collected for gating `decl_macro`, e.g. `macro m() {}`. - pub decl_macro: Lock>, - /// Spans collected for gating `box_patterns`, e.g. `box 0`. - pub box_patterns: Lock>, - /// Spans collected for gating `exclusive_range_pattern`, e.g. `0..2`. - pub exclusive_range_pattern: Lock>, - /// Spans collected for gating `try_blocks`, e.g. `try { a? + b? }`. - pub try_blocks: Lock>, - /// Spans collected for gating `label_break_value`, e.g. `'label: { ... }`. - pub label_break_value: Lock>, - /// Spans collected for gating `box_syntax`, e.g. `box $expr`. - pub box_syntax: Lock>, - /// Spans collected for gating `type_ascription`, e.g. `42: usize`. - pub type_ascription: Lock>, +pub struct GatedSpans { + pub spans: Lock>>, +} + +impl GatedSpans { + /// Feature gate the given `span` under the given `feature` + /// which is same `Symbol` used in `active.rs`. + pub fn gate(&self, feature: Symbol, span: Span) { + self.spans + .borrow_mut() + .entry(feature) + .or_default() + .push(span); + } + + /// Ungate the last span under the given `feature`. + /// Panics if the given `span` wasn't the last one. + /// + /// Using this is discouraged unless you have a really good reason to. + pub fn ungate_last(&self, feature: Symbol, span: Span) { + let removed_span = self.spans + .borrow_mut() + .entry(feature) + .or_default() + .pop() + .unwrap(); + debug_assert_eq!(span, removed_span); + } + + /// Is the provided `feature` gate ungated currently? + /// + /// Using this is discouraged unless you have a really good reason to. + pub fn is_ungated(&self, feature: Symbol) -> bool { + self.spans + .borrow() + .get(&feature) + .map_or(true, |spans| spans.is_empty()) + } + + /// Prepend the given set of `spans` onto the set in `self`. + pub fn merge(&self, mut spans: FxHashMap>) { + let mut inner = self.spans.borrow_mut(); + for (gate, mut gate_spans) in inner.drain() { + spans.entry(gate).or_default().append(&mut gate_spans); + } + *inner = spans; + } } /// Info about a parsing session. @@ -72,7 +86,7 @@ pub struct ParseSess { /// analysis. pub ambiguous_block_expr_parse: Lock>, pub injected_crate_name: Once, - crate gated_spans: GatedSpans, + pub gated_spans: GatedSpans, /// The parser has reached `Eof` due to an unclosed brace. Used to silence unnecessary errors. pub reached_eof: Lock, } diff --git a/src/libsyntax_expand/Cargo.toml b/src/libsyntax_expand/Cargo.toml index d98b9457a625f..02c711bc387e3 100644 --- a/src/libsyntax_expand/Cargo.toml +++ b/src/libsyntax_expand/Cargo.toml @@ -21,6 +21,5 @@ errors = { path = "../librustc_errors", package = "rustc_errors" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_index = { path = "../librustc_index" } rustc_lexer = { path = "../librustc_lexer" } -rustc_target = { path = "../librustc_target" } smallvec = { version = "1.0", features = ["union", "may_dangle"] } syntax = { path = "../libsyntax" } diff --git a/src/libsyntax_expand/mbe/macro_rules.rs b/src/libsyntax_expand/mbe/macro_rules.rs index 7a772b0d31dab..5571990740317 100644 --- a/src/libsyntax_expand/mbe/macro_rules.rs +++ b/src/libsyntax_expand/mbe/macro_rules.rs @@ -29,7 +29,7 @@ use syntax_pos::Span; use rustc_data_structures::fx::FxHashMap; use std::borrow::Cow; use std::collections::hash_map::Entry; -use std::slice; +use std::{mem, slice}; use errors::Applicability; use rustc_data_structures::sync::Lrc; @@ -182,7 +182,6 @@ fn generic_extension<'cx>( // Which arm's failure should we report? (the one furthest along) let mut best_failure: Option<(Token, &str)> = None; - for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers let lhs_tt = match *lhs { @@ -190,8 +189,18 @@ fn generic_extension<'cx>( _ => cx.span_bug(sp, "malformed macro lhs"), }; + // Take a snapshot of the state of pre-expansion gating at this point. + // This is used so that if a matcher is not `Success(..)`ful, + // then the spans which became gated when parsing the unsucessful matcher + // are not recorded. On the first `Success(..)`ful matcher, the spans are merged. + let mut gated_spans_snaphot = mem::take(&mut *cx.parse_sess.gated_spans.spans.borrow_mut()); + match parse_tt(cx, lhs_tt, arg.clone()) { Success(named_matches) => { + // The matcher was `Success(..)`ful. + // Merge the gated spans from parsing the matcher with the pre-existing ones. + cx.parse_sess.gated_spans.merge(gated_spans_snaphot); + let rhs = match rhses[i] { // ignore delimiters mbe::TokenTree::Delimited(_, ref delimed) => delimed.tts.clone(), @@ -248,6 +257,10 @@ fn generic_extension<'cx>( }, Error(err_sp, ref msg) => cx.span_fatal(err_sp.substitute_dummy(sp), &msg[..]), } + + // The matcher was not `Success(..)`ful. + // Restore to the state before snapshotting and maybe try again. + mem::swap(&mut gated_spans_snaphot, &mut cx.parse_sess.gated_spans.spans.borrow_mut()); } let (token, label) = best_failure.expect("ran no matchers"); diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs index 47bade698a80a..4bf13f3771102 100644 --- a/src/libsyntax_ext/concat.rs +++ b/src/libsyntax_ext/concat.rs @@ -21,8 +21,7 @@ pub fn expand_concat( match e.kind { ast::ExprKind::Lit(ref lit) => match lit.kind { ast::LitKind::Str(ref s, _) - | ast::LitKind::Float(ref s, _) - | ast::LitKind::FloatUnsuffixed(ref s) => { + | ast::LitKind::Float(ref s, _) => { accumulator.push_str(&s.as_str()); } ast::LitKind::Char(c) => { diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 2e5ae235893cb..b18fd50ae7605 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -182,8 +182,7 @@ use std::iter; use std::vec; use rustc_data_structures::thin_vec::ThinVec; -use rustc_target::spec::abi::Abi; -use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind}; +use syntax::ast::{self, Abi, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind}; use syntax::ast::{VariantData, GenericParamKind, GenericArg}; use syntax::attr; use syntax::source_map::respan; @@ -738,7 +737,7 @@ impl<'a> TraitDef<'a> { self, type_ident, generics, - Abi::Rust, + sym::Rust, explicit_self, tys, body) @@ -793,7 +792,7 @@ impl<'a> TraitDef<'a> { self, type_ident, generics, - Abi::Rust, + sym::Rust, explicit_self, tys, body) @@ -919,7 +918,7 @@ impl<'a> MethodDef<'a> { trait_: &TraitDef<'_>, type_ident: Ident, generics: &Generics, - abi: Abi, + abi: Symbol, explicit_self: Option, arg_types: Vec<(Ident, P)>, body: P) @@ -949,23 +948,27 @@ impl<'a> MethodDef<'a> { ast::Unsafety::Normal }; + let trait_lo_sp = trait_.span.shrink_to_lo(); + + let sig = ast::MethodSig { + header: ast::FnHeader { + unsafety, + abi: Abi::new(abi, trait_lo_sp), + ..ast::FnHeader::default() + }, + decl: fn_decl, + }; + // Create the method. ast::ImplItem { id: ast::DUMMY_NODE_ID, attrs: self.attributes.clone(), generics: fn_generics, span: trait_.span, - vis: respan(trait_.span.shrink_to_lo(), ast::VisibilityKind::Inherited), + vis: respan(trait_lo_sp, ast::VisibilityKind::Inherited), defaultness: ast::Defaultness::Final, ident: method_ident, - kind: ast::ImplItemKind::Method(ast::MethodSig { - header: ast::FnHeader { - unsafety, abi, - ..ast::FnHeader::default() - }, - decl: fn_decl, - }, - body_block), + kind: ast::ImplItemKind::Method(sig, body_block), tokens: None, } } diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 64ea82e1bdc53..d87b17eee3109 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -566,6 +566,7 @@ symbols! { rust_2018_preview, rust_begin_unwind, rustc, + Rust, RustcDecodable, RustcEncodable, rustc_allocator, diff --git a/src/libtest/tests.rs b/src/libtest/tests.rs index 9de774555e9cc..e0e211444cff5 100644 --- a/src/libtest/tests.rs +++ b/src/libtest/tests.rs @@ -269,7 +269,7 @@ fn time_test_failure_template(test_type: TestType) -> TestResult { fn test_error_on_exceed() { let types = [TestType::UnitTest, TestType::IntegrationTest, TestType::DocTest]; - for test_type in types.into_iter() { + for test_type in types.iter() { let result = time_test_failure_template(*test_type); assert_eq!(result, TestResult::TrTimedFail); @@ -320,7 +320,7 @@ fn test_time_options_threshold() { (TestType::DocTest, doc.critical.as_millis(), true, true), ]; - for (test_type, time, expected_warn, expected_critical) in test_vector.into_iter() { + for (test_type, time, expected_warn, expected_critical) in test_vector.iter() { let test_desc = typed_test_desc(*test_type); let exec_time = test_exec_time(*time as u64); diff --git a/src/test/ui/feature-gated-feature-in-macro-arg.stderr b/src/test/ui/feature-gated-feature-in-macro-arg.stderr index 5ee05154c3a2a..218e0292776d0 100644 --- a/src/test/ui/feature-gated-feature-in-macro-arg.stderr +++ b/src/test/ui/feature-gated-feature-in-macro-arg.stderr @@ -1,10 +1,8 @@ error[E0658]: intrinsics are subject to change - --> $DIR/feature-gated-feature-in-macro-arg.rs:8:9 + --> $DIR/feature-gated-feature-in-macro-arg.rs:8:16 | -LL | / extern "rust-intrinsic" { -LL | | fn atomic_fence(); -LL | | } - | |_________^ +LL | extern "rust-intrinsic" { + | ^^^^^^^^^^^^^^^^ | = help: add `#![feature(intrinsics)]` to the crate attributes to enable diff --git a/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr b/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr index 0d2e355535dee..d58a2d91b2b7f 100644 --- a/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr +++ b/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr @@ -1,8 +1,8 @@ error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi-msp430-interrupt.rs:4:1 + --> $DIR/feature-gate-abi-msp430-interrupt.rs:4:8 | LL | extern "msp430-interrupt" fn foo() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/38487 = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable diff --git a/src/test/ui/feature-gates/feature-gate-abi.stderr b/src/test/ui/feature-gates/feature-gate-abi.stderr index 0f2622f106595..6db6cb49cef14 100644 --- a/src/test/ui/feature-gates/feature-gate-abi.stderr +++ b/src/test/ui/feature-gates/feature-gate-abi.stderr @@ -1,591 +1,591 @@ error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:13:1 + --> $DIR/feature-gate-abi.rs:13:8 | LL | extern "rust-intrinsic" fn f1() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:15:1 + --> $DIR/feature-gate-abi.rs:15:8 | LL | extern "platform-intrinsic" fn f2() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/27731 = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:17:1 + --> $DIR/feature-gate-abi.rs:17:8 | LL | extern "vectorcall" fn f3() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:18:1 + --> $DIR/feature-gate-abi.rs:18:8 | LL | extern "rust-call" fn f4() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/29625 = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:19:1 + --> $DIR/feature-gate-abi.rs:19:8 | LL | extern "msp430-interrupt" fn f5() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/38487 = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:20:1 + --> $DIR/feature-gate-abi.rs:20:8 | LL | extern "ptx-kernel" fn f6() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/38788 = help: add `#![feature(abi_ptx)]` to the crate attributes to enable error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:21:1 + --> $DIR/feature-gate-abi.rs:21:8 | LL | extern "x86-interrupt" fn f7() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/40180 = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:22:1 + --> $DIR/feature-gate-abi.rs:22:8 | LL | extern "thiscall" fn f8() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ | = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:23:1 + --> $DIR/feature-gate-abi.rs:23:8 | LL | extern "amdgpu-kernel" fn f9() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/51575 = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:24:1 + --> $DIR/feature-gate-abi.rs:24:8 | LL | extern "efiapi" fn f10() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/65815 = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:28:5 + --> $DIR/feature-gate-abi.rs:28:12 | LL | extern "rust-intrinsic" fn m1(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:30:5 + --> $DIR/feature-gate-abi.rs:30:12 | LL | extern "platform-intrinsic" fn m2(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/27731 = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:32:5 + --> $DIR/feature-gate-abi.rs:32:12 | LL | extern "vectorcall" fn m3(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:33:5 + --> $DIR/feature-gate-abi.rs:33:12 | LL | extern "rust-call" fn m4(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/29625 = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:34:5 + --> $DIR/feature-gate-abi.rs:34:12 | LL | extern "msp430-interrupt" fn m5(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/38487 = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:35:5 + --> $DIR/feature-gate-abi.rs:35:12 | LL | extern "ptx-kernel" fn m6(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/38788 = help: add `#![feature(abi_ptx)]` to the crate attributes to enable error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:36:5 + --> $DIR/feature-gate-abi.rs:36:12 | LL | extern "x86-interrupt" fn m7(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/40180 = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:37:5 + --> $DIR/feature-gate-abi.rs:37:12 | LL | extern "thiscall" fn m8(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ | = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:38:5 + --> $DIR/feature-gate-abi.rs:38:12 | LL | extern "amdgpu-kernel" fn m9(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/51575 = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:39:5 + --> $DIR/feature-gate-abi.rs:39:12 | LL | extern "efiapi" fn m10(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/65815 = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:41:5 + --> $DIR/feature-gate-abi.rs:41:12 | LL | extern "vectorcall" fn dm3() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:42:5 + --> $DIR/feature-gate-abi.rs:42:12 | LL | extern "rust-call" fn dm4() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/29625 = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:43:5 + --> $DIR/feature-gate-abi.rs:43:12 | LL | extern "msp430-interrupt" fn dm5() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/38487 = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:44:5 + --> $DIR/feature-gate-abi.rs:44:12 | LL | extern "ptx-kernel" fn dm6() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/38788 = help: add `#![feature(abi_ptx)]` to the crate attributes to enable error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:45:5 + --> $DIR/feature-gate-abi.rs:45:12 | LL | extern "x86-interrupt" fn dm7() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/40180 = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:46:5 + --> $DIR/feature-gate-abi.rs:46:12 | LL | extern "thiscall" fn dm8() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ | = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:47:5 + --> $DIR/feature-gate-abi.rs:47:12 | LL | extern "amdgpu-kernel" fn dm9() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/51575 = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:48:5 + --> $DIR/feature-gate-abi.rs:48:12 | LL | extern "efiapi" fn dm10() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/65815 = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:55:5 + --> $DIR/feature-gate-abi.rs:55:12 | LL | extern "rust-intrinsic" fn m1() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:57:5 + --> $DIR/feature-gate-abi.rs:57:12 | LL | extern "platform-intrinsic" fn m2() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/27731 = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:59:5 + --> $DIR/feature-gate-abi.rs:59:12 | LL | extern "vectorcall" fn m3() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:60:5 + --> $DIR/feature-gate-abi.rs:60:12 | LL | extern "rust-call" fn m4() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/29625 = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:61:5 + --> $DIR/feature-gate-abi.rs:61:12 | LL | extern "msp430-interrupt" fn m5() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/38487 = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:62:5 + --> $DIR/feature-gate-abi.rs:62:12 | LL | extern "ptx-kernel" fn m6() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/38788 = help: add `#![feature(abi_ptx)]` to the crate attributes to enable error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:63:5 + --> $DIR/feature-gate-abi.rs:63:12 | LL | extern "x86-interrupt" fn m7() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/40180 = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:64:5 + --> $DIR/feature-gate-abi.rs:64:12 | LL | extern "thiscall" fn m8() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ | = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:65:5 + --> $DIR/feature-gate-abi.rs:65:12 | LL | extern "amdgpu-kernel" fn m9() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/51575 = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:66:5 + --> $DIR/feature-gate-abi.rs:66:12 | LL | extern "efiapi" fn m10() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/65815 = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:71:5 + --> $DIR/feature-gate-abi.rs:71:12 | LL | extern "rust-intrinsic" fn im1() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:73:5 + --> $DIR/feature-gate-abi.rs:73:12 | LL | extern "platform-intrinsic" fn im2() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/27731 = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:75:5 + --> $DIR/feature-gate-abi.rs:75:12 | LL | extern "vectorcall" fn im3() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:76:5 + --> $DIR/feature-gate-abi.rs:76:12 | LL | extern "rust-call" fn im4() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/29625 = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:77:5 + --> $DIR/feature-gate-abi.rs:77:12 | LL | extern "msp430-interrupt" fn im5() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/38487 = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:78:5 + --> $DIR/feature-gate-abi.rs:78:12 | LL | extern "ptx-kernel" fn im6() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/38788 = help: add `#![feature(abi_ptx)]` to the crate attributes to enable error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:79:5 + --> $DIR/feature-gate-abi.rs:79:12 | LL | extern "x86-interrupt" fn im7() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/40180 = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:80:5 + --> $DIR/feature-gate-abi.rs:80:12 | LL | extern "thiscall" fn im8() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ | = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:81:5 + --> $DIR/feature-gate-abi.rs:81:12 | LL | extern "amdgpu-kernel" fn im9() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/51575 = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:82:5 + --> $DIR/feature-gate-abi.rs:82:12 | LL | extern "efiapi" fn im10() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/65815 = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:86:11 + --> $DIR/feature-gate-abi.rs:86:18 | LL | type A1 = extern "rust-intrinsic" fn(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:87:11 + --> $DIR/feature-gate-abi.rs:87:18 | LL | type A2 = extern "platform-intrinsic" fn(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/27731 = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:88:11 + --> $DIR/feature-gate-abi.rs:88:18 | LL | type A3 = extern "vectorcall" fn(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:89:11 + --> $DIR/feature-gate-abi.rs:89:18 | LL | type A4 = extern "rust-call" fn(); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/29625 = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:90:11 + --> $DIR/feature-gate-abi.rs:90:18 | LL | type A5 = extern "msp430-interrupt" fn(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/38487 = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:91:11 + --> $DIR/feature-gate-abi.rs:91:18 | LL | type A6 = extern "ptx-kernel" fn (); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/38788 = help: add `#![feature(abi_ptx)]` to the crate attributes to enable error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:92:11 + --> $DIR/feature-gate-abi.rs:92:18 | LL | type A7 = extern "x86-interrupt" fn(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/40180 = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:93:11 + --> $DIR/feature-gate-abi.rs:93:18 | LL | type A8 = extern "thiscall" fn(); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ | = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:94:11 + --> $DIR/feature-gate-abi.rs:94:18 | LL | type A9 = extern "amdgpu-kernel" fn(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/51575 = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:95:12 + --> $DIR/feature-gate-abi.rs:95:19 | LL | type A10 = extern "efiapi" fn(); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/65815 = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:98:1 + --> $DIR/feature-gate-abi.rs:98:8 | LL | extern "rust-intrinsic" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:99:1 + --> $DIR/feature-gate-abi.rs:99:8 | LL | extern "platform-intrinsic" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/27731 = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:100:1 + --> $DIR/feature-gate-abi.rs:100:8 | LL | extern "vectorcall" {} - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:101:1 + --> $DIR/feature-gate-abi.rs:101:8 | LL | extern "rust-call" {} - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/29625 = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:102:1 + --> $DIR/feature-gate-abi.rs:102:8 | LL | extern "msp430-interrupt" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/38487 = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:103:1 + --> $DIR/feature-gate-abi.rs:103:8 | LL | extern "ptx-kernel" {} - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/38788 = help: add `#![feature(abi_ptx)]` to the crate attributes to enable error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:104:1 + --> $DIR/feature-gate-abi.rs:104:8 | LL | extern "x86-interrupt" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/40180 = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:105:1 + --> $DIR/feature-gate-abi.rs:105:8 | LL | extern "thiscall" {} - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ | = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:106:1 + --> $DIR/feature-gate-abi.rs:106:8 | LL | extern "amdgpu-kernel" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/51575 = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:107:1 + --> $DIR/feature-gate-abi.rs:107:8 | LL | extern "efiapi" {} - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/65815 = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable diff --git a/src/test/ui/feature-gates/feature-gate-abi_unadjusted.stderr b/src/test/ui/feature-gates/feature-gate-abi_unadjusted.stderr index 4954a7d1f71f6..1757befec35c0 100644 --- a/src/test/ui/feature-gates/feature-gate-abi_unadjusted.stderr +++ b/src/test/ui/feature-gates/feature-gate-abi_unadjusted.stderr @@ -1,10 +1,8 @@ error[E0658]: unadjusted ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi_unadjusted.rs:1:1 + --> $DIR/feature-gate-abi_unadjusted.rs:1:8 | -LL | / extern "unadjusted" fn foo() { -LL | | -LL | | } - | |_^ +LL | extern "unadjusted" fn foo() { + | ^^^^^^^^^^^^ | = help: add `#![feature(abi_unadjusted)]` to the crate attributes to enable diff --git a/src/test/ui/feature-gates/feature-gate-intrinsics.stderr b/src/test/ui/feature-gates/feature-gate-intrinsics.stderr index 101a10e8df71f..8f943d357ce02 100644 --- a/src/test/ui/feature-gates/feature-gate-intrinsics.stderr +++ b/src/test/ui/feature-gates/feature-gate-intrinsics.stderr @@ -1,18 +1,16 @@ error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-intrinsics.rs:1:1 + --> $DIR/feature-gate-intrinsics.rs:1:8 | -LL | / extern "rust-intrinsic" { -LL | | fn bar(); -LL | | } - | |_^ +LL | extern "rust-intrinsic" { + | ^^^^^^^^^^^^^^^^ | = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-intrinsics.rs:5:1 + --> $DIR/feature-gate-intrinsics.rs:5:8 | LL | extern "rust-intrinsic" fn baz() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: add `#![feature(intrinsics)]` to the crate attributes to enable diff --git a/src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr b/src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr index c05379c71eeaf..657bf13c8739e 100644 --- a/src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr +++ b/src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr @@ -1,35 +1,35 @@ error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:11:5 + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:11:12 | LL | extern "rust-call" fn call(self, args: ()) -> () {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/29625 = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:17:5 + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:17:12 | LL | extern "rust-call" fn call_once(self, args: ()) -> () {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/29625 = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:23:5 + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:23:12 | LL | extern "rust-call" fn call_mut(&self, args: ()) -> () {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/29625 = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:29:5 + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:29:12 | LL | extern "rust-call" fn call_once(&self, args: ()) -> () {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/29625 = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable diff --git a/src/test/ui/feature-gates/feature-gate-unboxed-closures.stderr b/src/test/ui/feature-gates/feature-gate-unboxed-closures.stderr index 723c6619887aa..f343a42eb8fa9 100644 --- a/src/test/ui/feature-gates/feature-gate-unboxed-closures.stderr +++ b/src/test/ui/feature-gates/feature-gate-unboxed-closures.stderr @@ -1,10 +1,8 @@ error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-unboxed-closures.rs:9:5 + --> $DIR/feature-gate-unboxed-closures.rs:9:12 | -LL | / extern "rust-call" fn call_once(self, (a, b): (u32, u32)) -> u32 { -LL | | a + b -LL | | } - | |_____^ +LL | extern "rust-call" fn call_once(self, (a, b): (u32, u32)) -> u32 { + | ^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/29625 = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable diff --git a/src/test/ui/impl-trait/trait_type.stderr b/src/test/ui/impl-trait/trait_type.stderr index 129d7ef5783ce..151dc68162155 100644 --- a/src/test/ui/impl-trait/trait_type.stderr +++ b/src/test/ui/impl-trait/trait_type.stderr @@ -29,7 +29,7 @@ error[E0046]: not all trait items implemented, missing: `fmt` LL | impl std::fmt::Display for MyType4 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `fmt` in implementation | - = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>` + = help: implement the missing item: `fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { unimplemented!() }` error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-3344.stderr b/src/test/ui/issues/issue-3344.stderr index 6593e07b18973..271fbb6c87426 100644 --- a/src/test/ui/issues/issue-3344.stderr +++ b/src/test/ui/issues/issue-3344.stderr @@ -4,7 +4,7 @@ error[E0046]: not all trait items implemented, missing: `partial_cmp` LL | impl PartialOrd for Thing { | ^^^^^^^^^^^^^^^^^^^^^^^^^ missing `partial_cmp` in implementation | - = note: `partial_cmp` from trait: `fn(&Self, &Rhs) -> std::option::Option` + = help: implement the missing item: `fn partial_cmp(&self, _: &Rhs) -> std::option::Option { unimplemented!() }` error: aborting due to previous error diff --git a/src/test/ui/iterators/into-iter-on-arrays-lint.fixed b/src/test/ui/iterators/into-iter-on-arrays-lint.fixed new file mode 100644 index 0000000000000..f88a52d315918 --- /dev/null +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.fixed @@ -0,0 +1,33 @@ +// run-pass +// run-rustfix + +fn main() { + let small = [1, 2]; + let big = [0u8; 33]; + + // Expressions that should trigger the lint + small.iter(); + //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this was previously accepted by the compiler but is being phased out + [1, 2].iter(); + //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this was previously accepted by the compiler but is being phased out + big.iter(); + //~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter` + //~| WARNING this was previously accepted by the compiler but is being phased out + [0u8; 33].iter(); + //~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter` + //~| WARNING this was previously accepted by the compiler but is being phased out + + + // Expressions that should not + (&[1, 2]).into_iter(); + (&small).into_iter(); + (&[0u8; 33]).into_iter(); + (&big).into_iter(); + + for _ in &[1, 2] {} + (&small as &[_]).into_iter(); + small[..].into_iter(); + std::iter::IntoIterator::into_iter(&[1, 2]); +} diff --git a/src/test/ui/iterators/into-iter-on-arrays-lint.rs b/src/test/ui/iterators/into-iter-on-arrays-lint.rs new file mode 100644 index 0000000000000..e1a4b535f3832 --- /dev/null +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.rs @@ -0,0 +1,33 @@ +// run-pass +// run-rustfix + +fn main() { + let small = [1, 2]; + let big = [0u8; 33]; + + // Expressions that should trigger the lint + small.into_iter(); + //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this was previously accepted by the compiler but is being phased out + [1, 2].into_iter(); + //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this was previously accepted by the compiler but is being phased out + big.into_iter(); + //~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter` + //~| WARNING this was previously accepted by the compiler but is being phased out + [0u8; 33].into_iter(); + //~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter` + //~| WARNING this was previously accepted by the compiler but is being phased out + + + // Expressions that should not + (&[1, 2]).into_iter(); + (&small).into_iter(); + (&[0u8; 33]).into_iter(); + (&big).into_iter(); + + for _ in &[1, 2] {} + (&small as &[_]).into_iter(); + small[..].into_iter(); + std::iter::IntoIterator::into_iter(&[1, 2]); +} diff --git a/src/test/ui/iterators/into-iter-on-arrays-lint.stderr b/src/test/ui/iterators/into-iter-on-arrays-lint.stderr new file mode 100644 index 0000000000000..b5964bd44bff7 --- /dev/null +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.stderr @@ -0,0 +1,37 @@ +warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. + --> $DIR/into-iter-on-arrays-lint.rs:9:11 + | +LL | small.into_iter(); + | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | + = note: `#[warn(array_into_iter)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #66145 + +warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. + --> $DIR/into-iter-on-arrays-lint.rs:12:12 + | +LL | [1, 2].into_iter(); + | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #66145 + +warning: this method call currently resolves to `<&[T] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. + --> $DIR/into-iter-on-arrays-lint.rs:15:9 + | +LL | big.into_iter(); + | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #66145 + +warning: this method call currently resolves to `<&[T] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. + --> $DIR/into-iter-on-arrays-lint.rs:18:15 + | +LL | [0u8; 33].into_iter(); + | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #66145 + diff --git a/src/test/ui/missing/missing-items/m2.stderr b/src/test/ui/missing/missing-items/m2.stderr index d2dac4ca6454a..f8243528d72cf 100644 --- a/src/test/ui/missing/missing-items/m2.stderr +++ b/src/test/ui/missing/missing-items/m2.stderr @@ -4,9 +4,9 @@ error[E0046]: not all trait items implemented, missing: `CONSTANT`, `Type`, `met LL | impl m1::X for X { | ^^^^^^^^^^^^^^^^ missing `CONSTANT`, `Type`, `method` in implementation | - = note: `CONSTANT` from trait: `const CONSTANT: u32;` - = note: `Type` from trait: `type Type;` - = note: `method` from trait: `fn(&Self, std::string::String) -> ::Type` + = help: implement the missing item: `const CONSTANT: u32 = 42;` + = help: implement the missing item: `type Type = Type;` + = help: implement the missing item: `fn method(&self, _: std::string::String) -> ::Type { unimplemented!() }` error: aborting due to previous error diff --git a/src/test/ui/parser/bad-lit-suffixes.rs b/src/test/ui/parser/bad-lit-suffixes.rs index 9f301db09956e..7db83674efc60 100644 --- a/src/test/ui/parser/bad-lit-suffixes.rs +++ b/src/test/ui/parser/bad-lit-suffixes.rs @@ -1,9 +1,9 @@ extern - "C"suffix //~ ERROR suffixes on an ABI spec are invalid + "C"suffix //~ ERROR suffixes on a string literal are invalid fn foo() {} extern - "C"suffix //~ ERROR suffixes on an ABI spec are invalid + "C"suffix //~ ERROR suffixes on a string literal are invalid {} fn main() { diff --git a/src/test/ui/parser/bad-lit-suffixes.stderr b/src/test/ui/parser/bad-lit-suffixes.stderr index 208fcf43d9177..6b0049298ffd2 100644 --- a/src/test/ui/parser/bad-lit-suffixes.stderr +++ b/src/test/ui/parser/bad-lit-suffixes.stderr @@ -1,10 +1,10 @@ -error: suffixes on an ABI spec are invalid +error: suffixes on a string literal are invalid --> $DIR/bad-lit-suffixes.rs:2:5 | LL | "C"suffix | ^^^^^^^^^ invalid suffix `suffix` -error: suffixes on an ABI spec are invalid +error: suffixes on a string literal are invalid --> $DIR/bad-lit-suffixes.rs:6:5 | LL | "C"suffix diff --git a/src/test/ui/parser/extern-abi-from-mac-literal-frag.rs b/src/test/ui/parser/extern-abi-from-mac-literal-frag.rs new file mode 100644 index 0000000000000..cb23f2c808c34 --- /dev/null +++ b/src/test/ui/parser/extern-abi-from-mac-literal-frag.rs @@ -0,0 +1,26 @@ +// check-pass + +// In this test we check that the parser accepts an ABI string when it +// comes from a macro `literal` fragment as opposed to a hardcoded string. + +fn main() {} + +macro_rules! abi_from_lit_frag { + ($abi:literal) => { + extern $abi { + fn _import(); + } + + extern $abi fn _export() {} + + type _PTR = extern $abi fn(); + } +} + +mod rust { + abi_from_lit_frag!("Rust"); +} + +mod c { + abi_from_lit_frag!("C"); +} diff --git a/src/test/ui/parser/extern-abi-raw-strings.rs b/src/test/ui/parser/extern-abi-raw-strings.rs new file mode 100644 index 0000000000000..fad855a21f6b1 --- /dev/null +++ b/src/test/ui/parser/extern-abi-raw-strings.rs @@ -0,0 +1,13 @@ +// check-pass + +// Check that the string literal in `extern lit` will accept raw strings. + +fn main() {} + +extern r#"C"# fn foo() {} + +extern r#"C"# { + fn bar(); +} + +type T = extern r#"C"# fn(); diff --git a/src/test/ui/parser/extern-abi-string-escaping.rs b/src/test/ui/parser/extern-abi-string-escaping.rs new file mode 100644 index 0000000000000..87bd31aabb67d --- /dev/null +++ b/src/test/ui/parser/extern-abi-string-escaping.rs @@ -0,0 +1,13 @@ +// check-pass + +// Check that the string literal in `extern lit` will escapes. + +fn main() {} + +extern "\x43" fn foo() {} + +extern "\x43" { + fn bar(); +} + +type T = extern "\x43" fn(); diff --git a/src/test/ui/parser/extern-abi-syntactic.rs b/src/test/ui/parser/extern-abi-syntactic.rs new file mode 100644 index 0000000000000..7d2bbfe8a0163 --- /dev/null +++ b/src/test/ui/parser/extern-abi-syntactic.rs @@ -0,0 +1,17 @@ +// check-pass + +// Check that from the grammar's point of view, +// the specific set of ABIs is not part of it. + +fn main() {} + +#[cfg(FALSE)] +extern "some_abi_that_we_are_sure_does_not_exist_semantically" fn foo() {} + +#[cfg(FALSE)] +extern "some_abi_that_we_are_sure_does_not_exist_semantically" { + fn foo(); +} + +#[cfg(FALSE)] +type T = extern "some_abi_that_we_are_sure_does_not_exist_semantically" fn(); diff --git a/src/test/ui/parser/issue-65846-rollback-gating-failing-matcher.rs b/src/test/ui/parser/issue-65846-rollback-gating-failing-matcher.rs new file mode 100644 index 0000000000000..9d68a7bffdeee --- /dev/null +++ b/src/test/ui/parser/issue-65846-rollback-gating-failing-matcher.rs @@ -0,0 +1,14 @@ +// run-pass + +// Test that failing macro matchers will not cause pre-expansion errors +// even though they use a feature that is pre-expansion gated. + +macro_rules! m { + ($e:expr) => { 0 }; // This fails on the input below due to `, foo`. + ($e:expr,) => { 1 }; // This also fails to match due to `foo`. + (box $e:expr, foo) => { 2 }; // Successful matcher, we should get `2`. +} + +fn main() { + assert_eq!(2, m!(box 42, foo)); +} diff --git a/src/test/ui/span/impl-wrong-item-for-trait.stderr b/src/test/ui/span/impl-wrong-item-for-trait.stderr index 81409aac2897d..f23f421edc7c5 100644 --- a/src/test/ui/span/impl-wrong-item-for-trait.stderr +++ b/src/test/ui/span/impl-wrong-item-for-trait.stderr @@ -64,7 +64,7 @@ error[E0046]: not all trait items implemented, missing: `fmt` LL | impl Debug for FooTypeForMethod { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `fmt` in implementation | - = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>` + = help: implement the missing item: `fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { unimplemented!() }` error: aborting due to 8 previous errors diff --git a/src/test/ui/span/issue-23729.stderr b/src/test/ui/span/issue-23729.stderr index 865fae917c5db..f88ce6c88db23 100644 --- a/src/test/ui/span/issue-23729.stderr +++ b/src/test/ui/span/issue-23729.stderr @@ -4,7 +4,7 @@ error[E0046]: not all trait items implemented, missing: `Item` LL | impl Iterator for Recurrence { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Item` in implementation | - = note: `Item` from trait: `type Item;` + = help: implement the missing item: `type Item = Type;` error: aborting due to previous error diff --git a/src/test/ui/span/issue-23827.stderr b/src/test/ui/span/issue-23827.stderr index a8e3e9b6b9ae9..46a820f1b7660 100644 --- a/src/test/ui/span/issue-23827.stderr +++ b/src/test/ui/span/issue-23827.stderr @@ -4,7 +4,7 @@ error[E0046]: not all trait items implemented, missing: `Output` LL | impl FnOnce<(C,)> for Prototype { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Output` in implementation | - = note: `Output` from trait: `type Output;` + = help: implement the missing item: `type Output = Type;` error: aborting due to previous error diff --git a/src/test/ui/span/issue-24356.stderr b/src/test/ui/span/issue-24356.stderr index 4827e9ddd50fd..a1f9b25502019 100644 --- a/src/test/ui/span/issue-24356.stderr +++ b/src/test/ui/span/issue-24356.stderr @@ -4,7 +4,7 @@ error[E0046]: not all trait items implemented, missing: `Target` LL | impl Deref for Thing { | ^^^^^^^^^^^^^^^^^^^^ missing `Target` in implementation | - = note: `Target` from trait: `type Target;` + = help: implement the missing item: `type Target = Type;` error: aborting due to previous error diff --git a/src/test/ui/suggestions/missing-trait-item.fixed b/src/test/ui/suggestions/missing-trait-item.fixed new file mode 100644 index 0000000000000..42f579a665e5f --- /dev/null +++ b/src/test/ui/suggestions/missing-trait-item.fixed @@ -0,0 +1,20 @@ +// run-rustfix + +trait T { + unsafe fn foo(a: &usize, b: &usize) -> usize; + fn bar(&self, a: &usize, b: &usize) -> usize; +} + +mod foo { + use super::T; + impl T for () { fn bar(&self, _: &usize, _: &usize) -> usize { unimplemented!() } + unsafe fn foo(_: &usize, _: &usize) -> usize { unimplemented!() } + } //~ ERROR not all trait items + + impl T for usize { //~ ERROR not all trait items + fn bar(&self, _: &usize, _: &usize) -> usize { unimplemented!() } + unsafe fn foo(_: &usize, _: &usize) -> usize { unimplemented!() } + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-trait-item.rs b/src/test/ui/suggestions/missing-trait-item.rs new file mode 100644 index 0000000000000..b4fca25ba2f11 --- /dev/null +++ b/src/test/ui/suggestions/missing-trait-item.rs @@ -0,0 +1,16 @@ +// run-rustfix + +trait T { + unsafe fn foo(a: &usize, b: &usize) -> usize; + fn bar(&self, a: &usize, b: &usize) -> usize; +} + +mod foo { + use super::T; + impl T for () {} //~ ERROR not all trait items + + impl T for usize { //~ ERROR not all trait items + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-trait-item.stderr b/src/test/ui/suggestions/missing-trait-item.stderr new file mode 100644 index 0000000000000..4a9d7b472c93a --- /dev/null +++ b/src/test/ui/suggestions/missing-trait-item.stderr @@ -0,0 +1,25 @@ +error[E0046]: not all trait items implemented, missing: `foo`, `bar` + --> $DIR/missing-trait-item.rs:10:5 + | +LL | unsafe fn foo(a: &usize, b: &usize) -> usize; + | --------------------------------------------- `foo` from trait +LL | fn bar(&self, a: &usize, b: &usize) -> usize; + | --------------------------------------------- `bar` from trait +... +LL | impl T for () {} + | ^^^^^^^^^^^^^ missing `foo`, `bar` in implementation + +error[E0046]: not all trait items implemented, missing: `foo`, `bar` + --> $DIR/missing-trait-item.rs:12:5 + | +LL | unsafe fn foo(a: &usize, b: &usize) -> usize; + | --------------------------------------------- `foo` from trait +LL | fn bar(&self, a: &usize, b: &usize) -> usize; + | --------------------------------------------- `bar` from trait +... +LL | impl T for usize { + | ^^^^^^^^^^^^^^^^ missing `foo`, `bar` in implementation + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0046`.