diff options
| author | bors <bors@rust-lang.org> | 2022-11-16 15:55:30 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-11-16 15:55:30 +0000 |
| commit | e69336efe035c274f2ee66922cd9cac6015956ea (patch) | |
| tree | 75586b5b6990744696a789341a292c14f7ddcc78 /compiler | |
| parent | 63c748ee23ab7b6706655146f5b7c7f579811803 (diff) | |
| parent | 972ad00094d8405b1188e5a40c1378f2eb073223 (diff) | |
| download | rust-e69336efe035c274f2ee66922cd9cac6015956ea.tar.gz rust-e69336efe035c274f2ee66922cd9cac6015956ea.zip | |
Auto merge of #104492 - matthiaskrgr:rollup-3xyjynz, r=matthiaskrgr
Rollup of 8 pull requests
Successful merges:
- #103750 (Fix some misleading target feature aliases)
- #104137 (Issue error when -C link-self-contained option is used on unsupported platforms)
- #104317 (cleanup and dedupe CTFE and Miri error reporting)
- #104335 (Only do parser recovery on retried macro matching)
- #104394 (various cleanups to try to reduce the use of spans inside method resolution)
- #104459 (rustdoc: remove unused JS IIFE from main.js)
- #104462 (rustdoc: remove pointless CSS `.rightside { padding-right: 2px }`)
- #104466 (rustdoc: remove no-op CSS `#crate-search-div { display: inline-block }`)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
34 files changed, 278 insertions, 268 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index c0c6c76473b..5478caee57d 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -47,7 +47,7 @@ pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool { if let Err(err) = fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) { all_constants_ok = false; match err { - ErrorHandled::Reported(_) | ErrorHandled::Linted => { + ErrorHandled::Reported(_) => { fx.tcx.sess.span_err(constant.span, "erroneous constant encountered"); } ErrorHandled::TooGeneric => { diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index dd0daf2c38b..b9600da5c39 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -315,10 +315,10 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> { false } /* - adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512gfni, - avx512ifma, avx512pf, avx512vaes, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpclmulqdq, - avx512vpopcntdq, bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm, - sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, xsave, xsavec, xsaveopt, xsaves + adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512ifma, + avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq, + bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm, + sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves */ //false }) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index e1f54356228..4af1aaec0a1 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -163,6 +163,9 @@ pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2] ("x86", "rdrand") => smallvec!["rdrnd"], ("x86", "bmi1") => smallvec!["bmi"], ("x86", "cmpxchg16b") => smallvec!["cx16"], + // FIXME: These aliases are misleading, and should be removed before avx512_target_feature is + // stabilized. They must remain until std::arch switches off them. + // rust#100752 ("x86", "avx512vaes") => smallvec!["vaes"], ("x86", "avx512gfni") => smallvec!["gfni"], ("x86", "avx512vpclmulqdq") => smallvec!["vpclmulqdq"], diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 4445e5f6c3a..2091730af22 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1588,6 +1588,9 @@ fn detect_self_contained_mingw(sess: &Session) -> bool { /// We only provide such support for a very limited number of targets. fn self_contained(sess: &Session, crate_type: CrateType) -> bool { if let Some(self_contained) = sess.opts.cg.link_self_contained { + if sess.target.link_self_contained == LinkSelfContainedDefault::False { + sess.emit_err(errors::UnsupportedLinkSelfContained); + } return self_contained; } diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index bfc4515de09..ade50af0aee 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -530,3 +530,7 @@ pub enum AppleSdkRootError<'a> { pub struct ReadFileError { pub message: std::io::Error, } + +#[derive(Diagnostic)] +#[diag(codegen_ssa_unsupported_link_self_contained)] +pub struct UnsupportedLinkSelfContained; diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index da9aaf00ecf..f4a300ef2c5 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -189,7 +189,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( all_consts_ok = false; match err { // errored or at least linted - ErrorHandled::Reported(_) | ErrorHandled::Linted => {} + ErrorHandled::Reported(_) => {} ErrorHandled::TooGeneric => { span_bug!(const_.span, "codegen encountered polymorphic constant: {:?}", err) } diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index a4368303de5..002aaf0db13 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -179,6 +179,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ ("f16c", Some(sym::f16c_target_feature)), ("fma", None), ("fxsr", None), + ("gfni", Some(sym::avx512_target_feature)), ("lzcnt", None), ("movbe", Some(sym::movbe_target_feature)), ("pclmulqdq", None), @@ -195,6 +196,8 @@ const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ ("sse4a", Some(sym::sse4a_target_feature)), ("ssse3", None), ("tbm", Some(sym::tbm_target_feature)), + ("vaes", Some(sym::avx512_target_feature)), + ("vpclmulqdq", Some(sym::avx512_target_feature)), ("xsave", None), ("xsavec", None), ("xsaveopt", None), diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 4977a5d6bbf..e3dfd72d5f0 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -55,7 +55,7 @@ impl Error for ConstEvalErrKind {} /// When const-evaluation errors, this type is constructed with the resulting information, /// and then used to emit the error as a lint or hard error. #[derive(Debug)] -pub struct ConstEvalErr<'tcx> { +pub(super) struct ConstEvalErr<'tcx> { pub span: Span, pub error: InterpError<'tcx>, pub stacktrace: Vec<FrameInfo<'tcx>>, @@ -82,8 +82,8 @@ impl<'tcx> ConstEvalErr<'tcx> { ConstEvalErr { error: error.into_kind(), stacktrace, span } } - pub fn report_as_error(&self, tcx: TyCtxtAt<'tcx>, message: &str) -> ErrorHandled { - self.struct_error(tcx, message, |_| {}) + pub(super) fn report(&self, tcx: TyCtxtAt<'tcx>, message: &str) -> ErrorHandled { + self.report_decorated(tcx, message, |_| {}) } /// Create a diagnostic for this const eval error. @@ -95,7 +95,7 @@ impl<'tcx> ConstEvalErr<'tcx> { /// If `lint_root.is_some()` report it as a lint, else report it as a hard error. /// (Except that for some errors, we ignore all that -- see `must_error` below.) #[instrument(skip(self, tcx, decorate), level = "debug")] - pub fn struct_error( + pub(super) fn report_decorated( &self, tcx: TyCtxtAt<'tcx>, message: &str, diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 8f5e503d659..f5942deaf9f 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -255,7 +255,7 @@ pub fn eval_to_const_value_raw_provider<'tcx>( return eval_nullary_intrinsic(tcx, key.param_env, def_id, substs).map_err(|error| { let span = tcx.def_span(def_id); let error = ConstEvalErr { error: error.into_kind(), stacktrace: vec![], span }; - error.report_as_error(tcx.at(span), "could not evaluate nullary intrinsic") + error.report(tcx.at(span), "could not evaluate nullary intrinsic") }); } @@ -333,7 +333,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>( } }; - Err(err.report_as_error(ecx.tcx.at(err.span), &msg)) + Err(err.report(ecx.tcx.at(err.span), &msg)) } Ok(mplace) => { // Since evaluation had no errors, validate the resulting constant. @@ -358,7 +358,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>( if let Err(error) = validation { // Validation failed, report an error. This is always a hard error. let err = ConstEvalErr::new(&ecx, error, None); - Err(err.struct_error( + Err(err.report_decorated( ecx.tcx, "it is undefined behavior to use this value", |diag| { diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index 1c33e7845cb..01b2b4b5d9c 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -103,7 +103,7 @@ pub(crate) fn try_destructure_mir_constant<'tcx>( ) -> InterpResult<'tcx, mir::DestructuredConstant<'tcx>> { trace!("destructure_mir_constant: {:?}", val); let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false); - let op = ecx.const_to_op(&val, None)?; + let op = ecx.eval_mir_constant(&val, None, None)?; // We go to `usize` as we cannot allocate anything bigger anyway. let (field_count, variant, down) = match val.ty().kind() { @@ -139,7 +139,7 @@ pub(crate) fn deref_mir_constant<'tcx>( val: mir::ConstantKind<'tcx>, ) -> mir::ConstantKind<'tcx> { let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false); - let op = ecx.const_to_op(&val, None).unwrap(); + let op = ecx.eval_mir_constant(&val, None, None).unwrap(); let mplace = ecx.deref_operand(&op).unwrap(); if let Some(alloc_id) = mplace.ptr.provenance { assert_eq!( diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index ab82268dde3..ed69d8554d2 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -5,7 +5,7 @@ use std::mem; use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData}; use rustc_index::vec::IndexVec; use rustc_middle::mir; -use rustc_middle::mir::interpret::{InterpError, InvalidProgramInfo}; +use rustc_middle::mir::interpret::{ErrorHandled, InterpError, InvalidProgramInfo}; use rustc_middle::ty::layout::{ self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout, @@ -696,12 +696,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { for ct in &body.required_consts { let span = ct.span; let ct = self.subst_from_current_frame_and_normalize_erasing_regions(ct.literal)?; - self.const_to_op(&ct, None).map_err(|err| { - // If there was an error, set the span of the current frame to this constant. - // Avoiding doing this when evaluation succeeds. - self.frame_mut().loc = Err(span); - err - })?; + self.eval_mir_constant(&ct, Some(span), None)?; } // Most locals are initially dead. @@ -912,9 +907,32 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(()) } - pub fn eval_to_allocation( + /// Call a query that can return `ErrorHandled`. If `span` is `Some`, point to that span when an error occurs. + pub fn ctfe_query<T>( + &self, + span: Option<Span>, + query: impl FnOnce(TyCtxtAt<'tcx>) -> Result<T, ErrorHandled>, + ) -> InterpResult<'tcx, T> { + // Use a precise span for better cycle errors. + query(self.tcx.at(span.unwrap_or_else(|| self.cur_span()))).map_err(|err| { + match err { + ErrorHandled::Reported(err) => { + if let Some(span) = span { + // To make it easier to figure out where this error comes from, also add a note at the current location. + self.tcx.sess.span_note_without_error(span, "erroneous constant used"); + } + err_inval!(AlreadyReported(err)) + } + ErrorHandled::TooGeneric => err_inval!(TooGeneric), + } + .into() + }) + } + + pub fn eval_global( &self, gid: GlobalId<'tcx>, + span: Option<Span>, ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { // For statics we pick `ParamEnv::reveal_all`, because statics don't have generics // and thus don't care about the parameter environment. While we could just use @@ -927,8 +945,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.param_env }; let param_env = param_env.with_const(); - // Use a precise span for better cycle errors. - let val = self.tcx.at(self.cur_span()).eval_to_allocation_raw(param_env.and(gid))?; + let val = self.ctfe_query(span, |tcx| tcx.eval_to_allocation_raw(param_env.and(gid)))?; self.raw_const_to_mplace(val) } diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index e68456a1d73..6fc2407b778 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -177,8 +177,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { sym::type_name => self.tcx.mk_static_str(), _ => bug!(), }; - let val = - self.tcx.const_eval_global_id(self.param_env, gid, Some(self.tcx.span))?; + let val = self.ctfe_query(None, |tcx| { + tcx.const_eval_global_id(self.param_env, gid, Some(tcx.span)) + })?; let val = self.const_val_to_op(val, ty, Some(dest.layout))?; self.copy_op(&val, dest, /*allow_transmute*/ false)?; } diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 7c20d9138e1..528c1cb06c0 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -501,8 +501,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { throw_unsup!(ReadExternStatic(def_id)); } - // Use a precise span for better cycle errors. - (self.tcx.at(self.cur_span()).eval_static_initializer(def_id)?, Some(def_id)) + // We don't give a span -- statics don't need that, they cannot be generic or associated. + let val = self.ctfe_query(None, |tcx| tcx.eval_static_initializer(def_id))?; + (val, Some(def_id)) } }; M::before_access_global(*self.tcx, &self.machine, id, alloc, def_id, is_write)?; diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index f0a83b7a026..cf9202540c7 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -4,8 +4,9 @@ use rustc_hir::def::Namespace; use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter}; -use rustc_middle::ty::{ConstInt, Ty}; +use rustc_middle::ty::{ConstInt, Ty, ValTree}; use rustc_middle::{mir, ty}; +use rustc_span::Span; use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size, TagEncoding}; use rustc_target::abi::{VariantIdx, Variants}; @@ -527,14 +528,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Copy(place) | Move(place) => self.eval_place_to_op(place, layout)?, Constant(ref constant) => { - let val = + let c = self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal)?; // This can still fail: // * During ConstProp, with `TooGeneric` or since the `required_consts` were not all // checked yet. // * During CTFE, since promoteds in `const`/`static` initializer bodies can fail. - self.const_to_op(&val, layout)? + self.eval_mir_constant(&c, Some(constant.span), layout)? } }; trace!("{:?}: {:?}", mir_op, *op); @@ -549,9 +550,35 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ops.iter().map(|op| self.eval_operand(op, None)).collect() } - pub fn const_to_op( + fn eval_ty_constant( + &self, + val: ty::Const<'tcx>, + span: Option<Span>, + ) -> InterpResult<'tcx, ValTree<'tcx>> { + Ok(match val.kind() { + ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(..) => { + throw_inval!(TooGeneric) + } + ty::ConstKind::Error(reported) => { + throw_inval!(AlreadyReported(reported)) + } + ty::ConstKind::Unevaluated(uv) => { + let instance = self.resolve(uv.def, uv.substs)?; + let cid = GlobalId { instance, promoted: None }; + self.ctfe_query(span, |tcx| tcx.eval_to_valtree(self.param_env.and(cid)))? + .unwrap_or_else(|| bug!("unable to create ValTree for {uv:?}")) + } + ty::ConstKind::Bound(..) | ty::ConstKind::Infer(..) => { + span_bug!(self.cur_span(), "unexpected ConstKind in ctfe: {val:?}") + } + ty::ConstKind::Value(valtree) => valtree, + }) + } + + pub fn eval_mir_constant( &self, val: &mir::ConstantKind<'tcx>, + span: Option<Span>, layout: Option<TyAndLayout<'tcx>>, ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { // FIXME(const_prop): normalization needed b/c const prop lint in @@ -563,44 +590,20 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let val = self.tcx.normalize_erasing_regions(self.param_env, *val); match val { mir::ConstantKind::Ty(ct) => { - match ct.kind() { - ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(..) => { - throw_inval!(TooGeneric) - } - ty::ConstKind::Error(reported) => { - throw_inval!(AlreadyReported(reported)) - } - ty::ConstKind::Unevaluated(uv) => { - // NOTE: We evaluate to a `ValTree` here as a check to ensure - // we're working with valid constants, even though we never need it. - let instance = self.resolve(uv.def, uv.substs)?; - let cid = GlobalId { instance, promoted: None }; - let _valtree = self - .tcx - .eval_to_valtree(self.param_env.and(cid))? - .unwrap_or_else(|| bug!("unable to create ValTree for {uv:?}")); - - Ok(self.eval_to_allocation(cid)?.into()) - } - ty::ConstKind::Bound(..) | ty::ConstKind::Infer(..) => { - span_bug!(self.cur_span(), "unexpected ConstKind in ctfe: {ct:?}") - } - ty::ConstKind::Value(valtree) => { - let ty = ct.ty(); - let const_val = self.tcx.valtree_to_const_val((ty, valtree)); - self.const_val_to_op(const_val, ty, layout) - } - } + let ty = ct.ty(); + let valtree = self.eval_ty_constant(ct, span)?; + let const_val = self.tcx.valtree_to_const_val((ty, valtree)); + self.const_val_to_op(const_val, ty, layout) } mir::ConstantKind::Val(val, ty) => self.const_val_to_op(val, ty, layout), mir::ConstantKind::Unevaluated(uv, _) => { let instance = self.resolve(uv.def, uv.substs)?; - Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into()) + Ok(self.eval_global(GlobalId { instance, promoted: uv.promoted }, span)?.into()) } } } - pub(crate) fn const_val_to_op( + pub(super) fn const_val_to_op( &self, val_val: ConstValue<'tcx>, ty: Ty<'tcx>, diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl index eb6b403d00e..70ce559526c 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl @@ -184,3 +184,5 @@ codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}` codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {error} codegen_ssa_read_file = failed to read file: {message} + +codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 182fbe36919..c02680b77fb 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -22,7 +22,7 @@ use rustc_lint_defs::builtin::{ RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, }; use rustc_lint_defs::BuiltinLintDiagnostics; -use rustc_parse::parser::Parser; +use rustc_parse::parser::{Parser, Recovery}; use rustc_session::parse::ParseSess; use rustc_session::Session; use rustc_span::edition::Edition; @@ -219,6 +219,8 @@ pub(super) trait Tracker<'matcher> { /// For tracing. fn description() -> &'static str; + + fn recovery() -> Recovery; } /// A noop tracker that is used in the hot path of the expansion, has zero overhead thanks to monomorphization. @@ -230,6 +232,9 @@ impl<'matcher> Tracker<'matcher> for NoopTracker { fn description() -> &'static str { "none" } + fn recovery() -> Recovery { + Recovery::Forbidden + } } /// Expands the rules based macro defined by `lhses` and `rhses` for a given @@ -330,7 +335,12 @@ fn expand_macro<'cx>( let mut tracker = CollectTrackerAndEmitter::new(cx, sp); let try_success_result = try_match_macro(sess, name, &arg, lhses, &mut tracker); - assert!(try_success_result.is_err(), "Macro matching returned a success on the second try"); + + if try_success_result.is_ok() { + // Nonterminal parser recovery might turn failed matches into successful ones, + // but for that it must have emitted an error already + tracker.cx.sess.delay_span_bug(sp, "Macro matching returned a success on the second try"); + } if let Some(result) = tracker.result { // An irrecoverable error occurred and has been emitted. @@ -338,7 +348,7 @@ fn expand_macro<'cx>( } let Some((token, label, remaining_matcher)) = tracker.best_failure else { - return tracker.result.expect("must have encountered Error or ErrorReported"); + return DummyResult::any(sp); }; let span = token.span.substitute_dummy(sp); @@ -360,7 +370,7 @@ fn expand_macro<'cx>( // Check whether there's a missing comma in this macro call, like `println!("{}" a);` if let Some((arg, comma_span)) = arg.add_comma() { for lhs in lhses { - let parser = parser_from_cx(sess, arg.clone()); + let parser = parser_from_cx(sess, arg.clone(), Recovery::Allowed); let mut tt_parser = TtParser::new(name); if let Success(_) = @@ -406,7 +416,12 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, fn after_arm(&mut self, result: &NamedParseResult) { match result { Success(_) => { - unreachable!("should not collect detailed info for successful macro match"); + // Nonterminal parser recovery might turn failed matches into successful ones, + // but for that it must have emitted an error already + self.cx.sess.delay_span_bug( + self.root_span, + "should not collect detailed info for successful macro match", + ); } Failure(token, msg) => match self.best_failure { Some((ref best_token, _, _)) if best_token.span.lo() >= token.span.lo() => {} @@ -432,6 +447,10 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, fn description() -> &'static str { "detailed" } + + fn recovery() -> Recovery { + Recovery::Allowed + } } impl<'a, 'cx> CollectTrackerAndEmitter<'a, 'cx, '_> { @@ -477,7 +496,7 @@ fn try_match_macro<'matcher, T: Tracker<'matcher>>( // 68836 suggests a more comprehensive but more complex change to deal with // this situation.) // FIXME(Nilstrieb): Stop recovery from happening on this parser and retry later with recovery if the macro failed to match. - let parser = parser_from_cx(sess, arg.clone()); + let parser = parser_from_cx(sess, arg.clone(), T::recovery()); // Try each arm's matchers. let mut tt_parser = TtParser::new(name); for (i, lhs) in lhses.iter().enumerate() { @@ -1559,8 +1578,8 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String { } } -fn parser_from_cx(sess: &ParseSess, tts: TokenStream) -> Parser<'_> { - Parser::new(sess, tts, true, rustc_parse::MACRO_ARGUMENTS) +fn parser_from_cx(sess: &ParseSess, tts: TokenStream, recovery: Recovery) -> Parser<'_> { + Parser::new(sess, tts, true, rustc_parse::MACRO_ARGUMENTS).recovery(recovery) } /// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 2b019c8c9b7..ed2218b8746 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -504,7 +504,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // method lookup. let Ok(pick) = self .probe_for_name( - call_expr.span, Mode::MethodCall, segment.ident, IsSuggestion(true), diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 4a8b7749365..3f390cba3e7 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -93,17 +93,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_expr_id: hir::HirId, allow_private: bool, ) -> bool { - let mode = probe::Mode::MethodCall; match self.probe_for_name( - method_name.span, - mode, + probe::Mode::MethodCall, method_name, IsSuggestion(false), self_ty, call_expr_id, ProbeScope::TraitsInScope, ) { - Ok(..) => true, + Ok(pick) => { + pick.maybe_emit_unstable_name_collision_hint( + self.tcx, + method_name.span, + call_expr_id, + ); + true + } Err(NoMatch(..)) => false, Err(Ambiguity(..)) => true, Err(PrivateMatch(..)) => allow_private, @@ -125,10 +130,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { let params = self .probe_for_name( - method_name.span, probe::Mode::MethodCall, method_name, - IsSuggestion(false), + IsSuggestion(true), self_ty, call_expr.hir_id, ProbeScope::TraitsInScope, @@ -175,7 +179,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { args: &'tcx [hir::Expr<'tcx>], ) -> Result<MethodCallee<'tcx>, MethodError<'tcx>> { let pick = - self.lookup_probe(span, segment.ident, self_ty, call_expr, ProbeScope::TraitsInScope)?; + self.lookup_probe(segment.ident, self_ty, call_expr, ProbeScope::TraitsInScope)?; self.lint_dot_call_from_2018(self_ty, segment, span, call_expr, self_expr, &pick, args); @@ -200,13 +204,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .mk_ref(*region, ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() }); // We probe again to see if there might be a borrow mutability discrepancy. match self.lookup_probe( - span, segment.ident, trait_type, call_expr, ProbeScope::TraitsInScope, ) { - Ok(ref new_pick) if *new_pick != pick => { + Ok(ref new_pick) if pick.differs_from(new_pick) => { needs_mut = true; } _ => {} @@ -214,28 +217,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // We probe again, taking all traits into account (not only those in scope). - let mut candidates = match self.lookup_probe( - span, - segment.ident, - self_ty, - call_expr, - ProbeScope::AllTraits, - ) { - // If we find a different result the caller probably forgot to import a trait. - Ok(ref new_pick) if *new_pick != pick => vec![new_pick.item.container_id(self.tcx)], - Err(Ambiguity(ref sources)) => sources - .iter() - .filter_map(|source| { - match *source { - // Note: this cannot come from an inherent impl, - // because the first probing succeeded. - CandidateSource::Impl(def) => self.tcx.trait_id_of_impl(def), - CandidateSource::Trait(_) => None, - } - }) - .collect(), - _ => Vec::new(), - }; + let mut candidates = + match self.lookup_probe(segment.ident, self_ty, call_expr, ProbeScope::AllTraits) { + // If we find a different result the caller probably forgot to import a trait. + Ok(ref new_pick) if pick.differs_from(new_pick) => { + vec![new_pick.item.container_id(self.tcx)] + } + Err(Ambiguity(ref sources)) => sources + .iter() + .filter_map(|source| { + match *source { + // Note: this cannot come from an inherent impl, + // because the first probing succeeded. + CandidateSource::Impl(def) => self.tcx.trait_id_of_impl(def), + CandidateSource::Trait(_) => None, + } + }) + .collect(), + _ => Vec::new(), + }; candidates.retain(|candidate| *candidate != self.tcx.parent(result.callee.def_id)); return Err(IllegalSizedBound(candidates, needs_mut, span)); @@ -247,23 +247,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { #[instrument(level = "debug", skip(self, call_expr))] pub fn lookup_probe( &self, - span: Span, method_name: Ident, self_ty: Ty<'tcx>, call_expr: &'tcx hir::Expr<'tcx>, scope: ProbeScope, ) -> probe::PickResult<'tcx> { - let mode = probe::Mode::MethodCall; - let self_ty = self.resolve_vars_if_possible(self_ty); - self.probe_for_name( - span, - mode, + let pick = self.probe_for_name( + probe::Mode::MethodCall, method_name, IsSuggestion(false), self_ty, call_expr.hir_id, scope, - ) + )?; + pick.maybe_emit_unstable_name_collision_hint(self.tcx, method_name.span, call_expr.hir_id); + Ok(pick) } pub(super) fn obligation_for_method( @@ -587,7 +585,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let pick = self.probe_for_name( - span, probe::Mode::Path, method_name, IsSuggestion(false), @@ -596,6 +593,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ProbeScope::TraitsInScope, )?; + pick.maybe_emit_unstable_name_collision_hint(self.tcx, span, expr_id); + self.lint_fully_qualified_call_from_2018( span, method_name, diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 3fcd073f597..46a76085189 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -17,6 +17,7 @@ use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_middle::middle::stability; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; +use rustc_middle::ty::AssocItem; use rustc_middle::ty::GenericParamDefKind; use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitable}; use rustc_middle::ty::{InternalSubsts, SubstsRef}; @@ -83,8 +84,6 @@ struct ProbeContext<'a, 'tcx> { unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>, Option<ObligationCause<'tcx>>)>, - is_suggestion: IsSuggestion, - scope_expr_id: hir::HirId, } @@ -193,7 +192,7 @@ impl AutorefOrPtrAdjustment { } } -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, Clone)] pub struct Pick<'tcx> { pub item: ty::AssocItem, pub kind: PickKind<'tcx>, @@ -209,6 +208,9 @@ pub struct Pick<'tcx> { /// `*mut T`, convert it to `*const T`. pub autoref_or_ptr_adjustment: Option<AutorefOrPtrAdjustment>, pub self_ty: Ty<'tcx>, + + /// Unstable candidates alongside the stable ones. + unstable_candidates: Vec<(Candidate<'tcx>, Symbol)>, } #[derive(Clone, Debug, PartialEq, Eq)] @@ -298,7 +300,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { #[instrument(level = "debug", skip(self))] pub fn probe_for_name( &self, - span: Span, mode: Mode, item_name: Ident, is_suggestion: IsSuggestion, @@ -307,7 +308,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { scope: ProbeScope, ) -> PickResult<'tcx> { self.probe_op( - span, + item_name.span, mode, Some(item_name), None, @@ -446,7 +447,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return_type, orig_values, steps.steps, - is_suggestion, scope_expr_id, ); @@ -541,7 +541,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { return_type: Option<Ty<'tcx>>, orig_steps_var_values: OriginalQueryValues<'tcx>, steps: &'tcx [CandidateStep<'tcx>], - is_suggestion: IsSuggestion, scope_expr_id: hir::HirId, ) -> ProbeContext<'a, 'tcx> { ProbeContext { @@ -559,7 +558,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { allow_similar_names: false, private_candidate: None, unsatisfied_predicates: Vec::new(), - is_suggestion, scope_expr_id, } } @@ -881,7 +879,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } - pub fn matches_return_type( + fn matches_return_type( &self, method: &ty::AssocItem, self_ty: Option<Ty<'tcx>>, @@ -1052,26 +1050,17 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } fn pick_core(&mut self) -> Option<PickResult<'tcx>> { - let mut unstable_candidates = Vec::new(); - let pick = self.pick_all_method(Some(&mut unstable_candidates)); + let pick = self.pick_all_method(Some(&mut vec![])); // In this case unstable picking is done by `pick_method`. if !self.tcx.sess.opts.unstable_opts.pick_stable_methods_before_any_unstable { return pick; } - match pick { - // Emit a lint if there are unstable candidates alongside the stable ones. - // - // We suppress warning if we're picking the method only because it is a - // suggestion. - Some(Ok(ref p)) if !self.is_suggestion.0 && !unstable_candidates.is_empty() => { - self.emit_unstable_name_collision_hint(p, &unstable_candidates); - pick - } - Some(_) => pick, - None => self.pick_all_method(None), + if pick.is_none() { + return self.pick_all_method(None); } + pick } fn pick_all_method( @@ -1216,7 +1205,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { debug!("pick_method_with_unstable(self_ty={})", self.ty_to_string(self_ty)); let mut possibly_unsatisfied_predicates = Vec::new(); - let mut unstable_candidates = Vec::new(); for (kind, candidates) in &[("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)] @@ -1226,26 +1214,17 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self_ty, candidates.iter(), &mut possibly_unsatisfied_predicates, - Some(&mut unstable_candidates), + Some(&mut vec![]), ); - if let Some(pick) = res { - if !self.is_suggestion.0 && !unstable_candidates.is_empty() { - if let Ok(p) = &pick { - // Emit a lint if there are unstable candidates alongside the stable ones. - // - // We suppress warning if we're picking the method only because it is a - // suggestion. - self.emit_unstable_name_collision_hint(p, &unstable_candidates); - } - } - return Some(pick); + if res.is_some() { + return res; } } debug!("searching unstable candidates"); let res = self.consider_candidates( self_ty, - unstable_candidates.iter().map(|(c, _)| c), + self.inherent_candidates.iter().chain(&self.extension_candidates), &mut possibly_unsatisfied_predicates, None, ); @@ -1300,7 +1279,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { Option<ty::Predicate<'tcx>>, Option<ObligationCause<'tcx>>, )>, - unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>, + mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>, ) -> Option<PickResult<'tcx>> where ProbesIter: Iterator<Item = &'b Candidate<'tcx>> + Clone, @@ -1324,7 +1303,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } - if let Some(uc) = unstable_candidates { + if let Some(uc) = &mut unstable_candidates { applicable_candidates.retain(|&(p, _)| { if let stability::EvalResult::Deny { feature, .. } = self.tcx.eval_stability(p.item.def_id, None, self.span, None) @@ -1343,30 +1322,63 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { applicable_candidates.pop().map(|(probe, status)| { if status == ProbeResult::Match { - Ok(probe.to_unadjusted_pick(self_ty)) + Ok(probe + .to_unadjusted_pick(self_ty, unstable_candidates.cloned().unwrap_or_default())) } else { Err(MethodError::BadReturnType) } }) } +} + +impl<'tcx> Pick<'tcx> { + /// In case there were unstable name collisions, emit them as a lint. + /// Checks whether two picks do not refer to the same trait item for the same `Self` type. + /// Only useful for comparisons of picks in order to improve diagnostics. + /// Do not use for type checking. + pub fn differs_from(&self, other: &Self) -> bool { + let Self { + item: + AssocItem { + def_id, + name: _, + kind: _, + container: _, + trait_item_def_id: _, + fn_has_self_parameter: _, + }, + kind: _, + import_ids: _, + autoderefs: _, + autoref_or_ptr_adjustment: _, + self_ty, + unstable_candidates: _, + } = *self; + self_ty != other.self_ty || def_id != other.item.def_id + } - fn emit_unstable_name_collision_hint( + /// In case there were unstable name collisions, emit them as a lint. + pub fn maybe_emit_unstable_name_collision_hint( &self, - stable_pick: &Pick<'_>, - unstable_candidates: &[(Candidate<'tcx>, Symbol)], + tcx: TyCtxt<'tcx>, + span: Span, + scope_expr_id: hir::HirId, ) { - let def_kind = stable_pick.item.kind.as_def_kind(); - self.tcx.struct_span_lint_hir( + if self.unstable_candidates.is_empty() { + return; + } + let def_kind = self.item.kind.as_def_kind(); + tcx.struct_span_lint_hir( lint::builtin::UNSTABLE_NAME_COLLISIONS, - self.scope_expr_id, - self.span, + scope_expr_id, + span, format!( "{} {} with this name may be added to the standard library in the future", def_kind.article(), - def_kind.descr(stable_pick.item.def_id), + def_kind.descr(self.item.def_id), ), |lint| { - match (stable_pick.item.kind, stable_pick.item.container) { + match (self.item.kind, self.item.container) { (ty::AssocKind::Fn, _) => { // FIXME: This should be a `span_suggestion` instead of `help` // However `self.span` only @@ -1375,31 +1387,31 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { lint.help(&format!( "call with fully qualified syntax `{}(...)` to keep using the current \ method", - self.tcx.def_path_str(stable_pick.item.def_id), + tcx.def_path_str(self.item.def_id), )); } (ty::AssocKind::Const, ty::AssocItemContainer::TraitContainer) => { - let def_id = stable_pick.item.container_id(self.tcx); + let def_id = self.item.container_id(tcx); lint.span_suggestion( - self.span, + span, "use the fully qualified path to the associated const", format!( "<{} as {}>::{}", - stable_pick.self_ty, - self.tcx.def_path_str(def_id), - stable_pick.item.name + self.self_ty, + tcx.def_path_str(def_id), + self.item.name ), Applicability::MachineApplicable, ); } _ => {} } - if self.tcx.sess.is_nightly_build() { - for (candidate, feature) in unstable_candidates { + if tcx.sess.is_nightly_build() { + for (candidate, feature) in &self.unstable_candidates { lint.help(&format!( "add `#![feature({})]` to the crate attributes to enable `{}`", feature, - self.tcx.def_path_str(candidate.item.def_id), + tcx.def_path_str(candidate.item.def_id), )); } } @@ -1408,7 +1420,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { }, ); } +} +impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn select_trait_candidate( &self, trait_ref: ty::TraitRef<'tcx>, @@ -1667,6 +1681,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { autoderefs: 0, autoref_or_ptr_adjustment: None, self_ty, + unstable_candidates: vec![], }) } @@ -1686,7 +1701,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.return_type, self.orig_steps_var_values.clone(), steps, - IsSuggestion(true), self.scope_expr_id, ); pcx.allow_similar_names = true; @@ -1894,7 +1908,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } impl<'tcx> Candidate<'tcx> { - fn to_unadjusted_pick(&self, self_ty: Ty<'tcx>) -> Pick<'tcx> { + fn to_unadjusted_pick( + &self, + self_ty: Ty<'tcx>, + unstable_candidates: Vec<(Candidate<'tcx>, Symbol)>, + ) -> Pick<'tcx> { Pick { item: self.item, kind: match self.kind { @@ -1919,6 +1937,7 @@ impl<'tcx> Candidate<'tcx> { autoderefs: 0, autoref_or_ptr_adjustment: None, self_ty, + unstable_candidates, } } } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index edfe12963dc..19f56c73823 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -376,7 +376,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .hir() .expect_expr(self.tcx.hir().get_parent_node(rcvr_expr.hir_id)); let probe = self.lookup_probe( - span, item_name, output_ty, call_expr, @@ -914,7 +913,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - self.check_for_inner_self(&mut err, source, span, rcvr_ty, item_name); + self.check_for_inner_self(&mut err, source, rcvr_ty, item_name); bound_spans.sort(); bound_spans.dedup(); @@ -1321,7 +1320,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]); let pick = self.probe_for_name( - span, Mode::MethodCall, item_name, IsSuggestion(true), @@ -1500,7 +1498,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, &|_, field_ty| { self.lookup_probe( - span, item_name, field_ty, call_expr, @@ -1548,7 +1545,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, err: &mut Diagnostic, source: SelfSource<'tcx>, - span: Span, actual: Ty<'tcx>, item_name: Ident, ) { @@ -1571,15 +1567,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return None; } - self.lookup_probe( - span, - item_name, - field_ty, - call_expr, - ProbeScope::TraitsInScope, - ) - .ok() - .map(|pick| (variant, field, pick)) + self.lookup_probe(item_name, field_ty, call_expr, ProbeScope::TraitsInScope) + .ok() + .map(|pick| (variant, field, pick)) }) .collect(); @@ -1644,12 +1634,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let [first] = ***substs else { return; }; let ty::GenericArgKind::Type(ty) = first.unpack() else { return; }; let Ok(pick) = self.lookup_probe( - span, - item_name, - ty, - call_expr, - ProbeScope::TraitsInScope, - ) else { return; }; + item_name, + ty, + call_expr, + ProbeScope::TraitsInScope, + ) else { return; }; let name = self.ty_to_value_string(actual); let inner_id = kind.did(); @@ -1899,7 +1888,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let SelfSource::QPath(ty) = self_source else { return; }; for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) { if let Ok(pick) = self.probe_for_name( - ty.span, Mode::Path, item_name, IsSuggestion(true), @@ -2107,7 +2095,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "), (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"), ] { - match self.lookup_probe(span, item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) { + match self.lookup_probe(item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) { Ok(pick) => { // If the method is defined for the receiver we have, it likely wasn't `use`d. // We point at the method, but we just skip the rest of the check for arbitrary @@ -2141,7 +2129,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ] { if let Some(new_rcvr_t) = *rcvr_ty && let Ok(pick) = self.lookup_probe( - span, item_name, new_rcvr_t, rcvr, @@ -2522,7 +2509,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: method_name.span, }; let probe = self.lookup_probe( - expr.span, new_name, self_ty, self_expr, diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 1ea8baa3cae..ae0dbad8b08 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -16,8 +16,6 @@ pub enum ErrorHandled { /// Already reported an error for this evaluation, and the compilation is /// *guaranteed* to fail. Warnings/lints *must not* produce `Reported`. Reported(ErrorGuaranteed), - /// Already emitted a lint for this evaluation. - Linted, /// Don't emit an error, the evaluation failed because the MIR was generic /// and the substs didn't fully monomorphize it. TooGeneric, @@ -89,18 +87,6 @@ fn print_backtrace(backtrace: &Backtrace) { eprintln!("\n\nAn error occurred in miri:\n{}", backtrace); } -impl From<ErrorHandled> for InterpErrorInfo<'_> { - fn from(err: ErrorHandled) -> Self { - match err { - ErrorHandled::Reported(ErrorGuaranteed { .. }) | ErrorHandled::Linted => { - err_inval!(ReferencedConstant) - } - ErrorHandled::TooGeneric => err_inval!(TooGeneric), - } - .into() - } -} - impl From<ErrorGuaranteed> for InterpErrorInfo<'_> { fn from(err: ErrorGuaranteed) -> Self { InterpError::InvalidProgram(InvalidProgramInfo::AlreadyReported(err)).into() @@ -138,9 +124,6 @@ impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> { pub enum InvalidProgramInfo<'tcx> { /// Resolution can fail if we are in a too generic context. TooGeneric, - /// Cannot compute this constant because it depends on another one - /// which already produced an error. - ReferencedConstant, /// Abort in case errors are already reported. AlreadyReported(ErrorGuaranteed), /// An error occurred during layout computation. @@ -158,9 +141,11 @@ impl fmt::Display for InvalidProgramInfo<'_> { use InvalidProgramInfo::*; match self { TooGeneric => write!(f, "encountered overly generic constant"), - ReferencedConstant => write!(f, "referenced constant has errors"), AlreadyReported(ErrorGuaranteed { .. }) => { - write!(f, "encountered constants with type errors, stopping evaluation") + write!( + f, + "an error has already been reported elsewhere (this sould not usually be printed)" + ) } Layout(ref err) => write!(f, "{err}"), FnAbiAdjustForForeignAbi(ref err) => write!(f, "{err}"), diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 473894ac1ca..b6c6e9d559c 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -175,6 +175,8 @@ impl<'tcx> TyCtxt<'tcx> { impl<'tcx> TyCtxtAt<'tcx> { /// Evaluate a static's initializer, returning the allocation of the initializer's memory. + /// + /// The span is entirely ignored here, but still helpful for better query cycle errors. pub fn eval_static_initializer( self, def_id: DefId, @@ -187,6 +189,8 @@ impl<'tcx> TyCtxtAt<'tcx> { } /// Evaluate anything constant-like, returning the allocation of the final memory. + /// + /// The span is entirely ignored here, but still helpful for better query cycle errors. fn eval_to_allocation( self, gid: GlobalId<'tcx>, diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 12e9ebfeaec..63f5678d3c8 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2304,7 +2304,7 @@ impl<'tcx> ConstantKind<'tcx> { // FIXME: We might want to have a `try_eval`-like function on `Unevaluated` match tcx.const_eval_resolve(param_env, uneval, None) { Ok(val) => Self::Val(val, ty), - Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => self, + Err(ErrorHandled::TooGeneric) => self, Err(ErrorHandled::Reported(guar)) => { Self::Ty(tcx.const_error_with_guaranteed(ty, guar)) } diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index b0a2412ab15..137b59cf6c2 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -463,9 +463,7 @@ impl<'tcx> AdtDef<'tcx> { } Err(err) => { let msg = match err { - ErrorHandled::Reported(_) | ErrorHandled::Linted => { - "enum discriminant evaluation failed" - } + ErrorHandled::Reported(_) => "enum discriminant evaluation failed", ErrorHandled::TooGeneric => "enum discriminant depends on generics", }; tcx.sess.delay_span_bug(tcx.def_span(expr_did), msg); diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index c1c613f6c60..321cba693d9 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -226,7 +226,7 @@ impl<'tcx> ConstKind<'tcx> { // (which may be identity substs, see above), // can leak through `val` into the const we return. Ok(val) => Some(Ok(EvalResult::ValTree(val?))), - Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => None, + Err(ErrorHandled::TooGeneric) => None, Err(ErrorHandled::Reported(e)) => Some(Err(e)), } } @@ -237,7 +237,7 @@ impl<'tcx> ConstKind<'tcx> { // (which may be identity substs, see above), // can leak through `val` into the const we return. Ok(val) => Some(Ok(EvalResult::ConstVal(val))), - Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => None, + Err(ErrorHandled::TooGeneric) => None, Err(ErrorHandled::Reported(e)) => Some(Err(e)), } } diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 9b9f942b491..3f5890040c3 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -471,7 +471,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { return None; } - self.ecx.const_to_op(&c.literal, None).ok() + // No span, we don't want errors to be shown. + self.ecx.eval_mir_constant(&c.literal, None, None).ok() } /// Returns the value, if any, of evaluating `place`. diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 163446c52e4..786063d538c 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -5,7 +5,6 @@ use crate::const_prop::CanConstProp; use crate::const_prop::ConstPropMachine; use crate::const_prop::ConstPropMode; use crate::MirLint; -use rustc_const_eval::const_eval::ConstEvalErr; use rustc_const_eval::interpret::Immediate; use rustc_const_eval::interpret::{ self, InterpCx, InterpResult, LocalState, LocalValue, MemoryKind, OpTy, Scalar, StackPopCleanup, @@ -286,25 +285,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } /// Returns the value, if any, of evaluating `c`. - fn eval_constant( - &mut self, - c: &Constant<'tcx>, - _source_info: SourceInfo, - ) -> Option<OpTy<'tcx>> { + fn eval_constant(&mut self, c: &Constant<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> { // FIXME we need to revisit this for #67176 if c.needs_subst() { return None; } - match self.ecx.const_to_op(&c.literal, None) { - Ok(op) => Some(op), - Err(error) => { - let tcx = self.ecx.tcx.at(c.span); - let err = ConstEvalErr::new(&self.ecx, error, Some(c.span)); - err.report_as_error(tcx, "erroneous constant used"); - None - } - } + self.use_ecx(source_info, |this| this.ecx.eval_mir_constant(&c.literal, Some(c.span), None)) } /// Returns the value, if any, of evaluating `place`. diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index e296d4766c1..cdf8011d4f5 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -773,7 +773,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { match self.tcx.const_eval_resolve(param_env, ct.expand(), None) { // The `monomorphize` call should have evaluated that constant already. Ok(val) => val, - Err(ErrorHandled::Reported(_) | ErrorHandled::Linted) => return, + Err(ErrorHandled::Reported(_)) => return, Err(ErrorHandled::TooGeneric) => span_bug!( self.body.source_info(location).span, "collection encountered polymorphic constant: {:?}", @@ -788,7 +788,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { match self.tcx.const_eval_resolve(param_env, uv, None) { // The `monomorphize` call should have evaluated that constant already. Ok(val) => val, - Err(ErrorHandled::Reported(_) | ErrorHandled::Linted) => return, + Err(ErrorHandled::Reported(_)) => return, Err(ErrorHandled::TooGeneric) => span_bug!( self.body.source_info(location).span, "collection encountered polymorphic constant: {:?}", diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 14dc490fb02..13a38a17735 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -503,8 +503,8 @@ impl<'a> Parser<'a> { parser } - pub fn forbid_recovery(mut self) -> Self { - self.recovery = Recovery::Forbidden; + pub fn recovery(mut self, recovery: Recovery) -> Self { + self.recovery = recovery; self } diff --git a/compiler/rustc_target/src/spec/wasm32_wasi.rs b/compiler/rustc_target/src/spec/wasm32_wasi.rs index 93a956403e5..6f0bbf0672d 100644 --- a/compiler/rustc_target/src/spec/wasm32_wasi.rs +++ b/compiler/rustc_target/src/spec/wasm32_wasi.rs @@ -72,7 +72,8 @@ //! best we can with this target. Don't start relying on too much here unless //! you know what you're getting in to! -use super::{crt_objects, wasm_base, Cc, LinkerFlavor, Target}; +use super::crt_objects::{self, LinkSelfContainedDefault}; +use super::{wasm_base, Cc, LinkerFlavor, Target}; pub fn target() -> Target { let mut options = wasm_base::options(); @@ -83,6 +84,9 @@ pub fn target() -> Target { options.pre_link_objects_self_contained = crt_objects::pre_wasi_self_contained(); options.post_link_objects_self_contained = crt_objects::post_wasi_self_contained(); + // FIXME: Figure out cases in which WASM needs to link with a native toolchain. + options.link_self_contained = LinkSelfContainedDefault::True; + // Right now this is a bit of a workaround but we're currently saying that // the target by default has a static crt which we're taking as a signal // for "use the bundled crt". If that's turned off then the system's crt diff --git a/compiler/rustc_target/src/spec/wasm_base.rs b/compiler/rustc_target/src/spec/wasm_base.rs index 528a84a8b37..625d3b37c4f 100644 --- a/compiler/rustc_target/src/spec/wasm_base.rs +++ b/compiler/rustc_target/src/spec/wasm_base.rs @@ -1,4 +1,3 @@ -use super::crt_objects::LinkSelfContainedDefault; use super::{cvs, Cc, LinkerFlavor, PanicStrategy, RelocModel, TargetOptions, TlsModel}; pub fn options() -> TargetOptions { @@ -95,9 +94,6 @@ pub fn options() -> TargetOptions { pre_link_args, - // FIXME: Figure out cases in which WASM needs to link with a native toolchain. - link_self_contained: LinkSelfContainedDefault::True, - // This has no effect in LLVM 8 or prior, but in LLVM 9 and later when // PIC code is implemented this has quite a drastic effect if it stays // at the default, `pic`. In an effort to keep wasm binaries as minimal diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 1de85e2f288..db3ddc9208a 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -198,13 +198,6 @@ pub fn is_const_evaluatable<'tcx>( .sess .delay_span_bug(span, "Missing value for constant, but no error reported?"), )), - Err(ErrorHandled::Linted) => { - let reported = infcx - .tcx - .sess - .delay_span_bug(span, "constant in type had error reported as lint"); - Err(NotConstEvaluatable::Error(reported)) - } Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)), Ok(_) => Ok(()), } @@ -254,11 +247,6 @@ pub fn is_const_evaluatable<'tcx>( Err(err) }, - Err(ErrorHandled::Linted) => { - let reported = - infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint"); - Err(NotConstEvaluatable::Error(reported)) - } Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)), Ok(_) => Ok(()), } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index b486c07f354..4905bb69cc5 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -558,12 +558,6 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { NotConstEvaluatable::Error(reported), )), ), - (Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => { - span_bug!( - obligation.cause.span(), - "ConstEquate: const_eval_resolve returned an unexpected error" - ) - } (Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => { if c1.has_non_region_infer() || c2.has_non_region_infer() { ProcessResult::Unchanged diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index a12f67125bb..3a899c03b4c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -727,12 +727,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } (Err(ErrorHandled::Reported(_)), _) | (_, Err(ErrorHandled::Reported(_))) => Ok(EvaluatedToErr), - (Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => { - span_bug!( - obligation.cause.span(), - "ConstEquate: const_eval_resolve returned an unexpected error" - ) - } (Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => { if c1.has_non_region_infer() || c2.has_non_region_infer() { Ok(EvaluatedToAmbig) |
