diff options
52 files changed, 461 insertions, 380 deletions
diff --git a/compiler/rustc_ast/src/entry.rs b/compiler/rustc_ast/src/entry.rs index cd8a5a66920..dd231e286d5 100644 --- a/compiler/rustc_ast/src/entry.rs +++ b/compiler/rustc_ast/src/entry.rs @@ -4,11 +4,35 @@ use rustc_span::Symbol; #[derive(Debug)] pub enum EntryPointType { + /// This function is not an entrypoint. None, + /// This is a function called `main` at the root level. + /// ``` + /// fn main() {} + /// ``` MainNamed, + /// This is a function with the `#[rustc_main]` attribute. + /// Used by the testing harness to create the test entrypoint. + /// ```ignore (clashes with test entrypoint) + /// #[rustc_main] + /// fn main() {} + /// ``` RustcMainAttr, + /// This is a function with the `#[start]` attribute. + /// ```ignore (clashes with test entrypoint) + /// #[start] + /// fn main() {} + /// ``` Start, - OtherMain, // Not an entry point, but some other function named main + /// This function is **not** an entrypoint but simply named `main` (not at the root). + /// This is only used for diagnostics. + /// ``` + /// #[allow(dead_code)] + /// mod meow { + /// fn main() {} + /// } + /// ``` + OtherMain, } pub fn entry_point_type( diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index a2015445b42..8cf431482ff 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -266,7 +266,7 @@ fn generate_test_harness( /// /// By default this expands to /// -/// ```ignore UNSOLVED (I think I still need guidance for this one. Is it correct? Do we try to make it run? How do we nicely fill it out?) +/// ```ignore (messes with test internals) /// #[rustc_main] /// pub fn main() { /// extern crate test; diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index e9cf5a3d769..6e6fa70107b 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -467,19 +467,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, let intrinsic_name = ecx.tcx.item_name(instance.def_id()); // CTFE-specific intrinsics. - let Some(ret) = target else { - // Handle diverging intrinsics. We can't handle any of them (that are not already - // handled above), but check if there is a fallback body. - if ecx.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden { - throw_unsup_format!( - "intrinsic `{intrinsic_name}` is not supported at compile-time" - ); - } - return Ok(Some(ty::Instance { - def: ty::InstanceDef::Item(instance.def_id()), - args: instance.args, - })); - }; match intrinsic_name { sym::ptr_guaranteed_cmp => { let a = ecx.read_scalar(&args[0])?; @@ -559,7 +546,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } } - ecx.go_to_block(ret); + // Intrinsic is done, jump to next block. + ecx.return_to_block(target)?; Ok(None) } diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index f73293856c7..88ce5a7cbeb 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -113,10 +113,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx, bool> { let instance_args = instance.args; let intrinsic_name = self.tcx.item_name(instance.def_id()); - let Some(ret) = ret else { - // We don't support any intrinsic without return place. - return Ok(false); - }; match intrinsic_name { sym::caller_location => { @@ -376,7 +372,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; M::panic_nounwind(self, &msg)?; - // Skip the `go_to_block` at the end. + // Skip the `return_to_block` at the end (we panicked, we do not return). return Ok(true); } } @@ -437,11 +433,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_scalar(Scalar::from_target_usize(align.bytes(), self), dest)?; } + // Unsupported intrinsic: skip the return_to_block below. _ => return Ok(false), } trace!("{:?}", self.dump_place(&dest.clone().into())); - self.go_to_block(ret); + self.return_to_block(ret)?; Ok(true) } diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 9c33cc8ed0b..dbb88e42a3e 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -518,7 +518,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // RFC 2397 gated!( do_not_recommend, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::No, experimental!(do_not_recommend) + EncodeCrossCrate::Yes, experimental!(do_not_recommend) ), // `#[cfi_encoding = ""]` diff --git a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs index e9a6276192e..3c423b4e2aa 100644 --- a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs +++ b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs @@ -164,9 +164,9 @@ pub(super) fn unexpected_cfg_name( if is_from_cargo { if !is_feature_cfg { - diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo:rustc-check-cfg={inst}\");` to the top of a `build.rs`")); + diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo::rustc-check-cfg={inst}\");` to the top of the `build.rs`")); } - diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration"); + diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration"); } else { diag.help(format!("to expect this configuration use `--check-cfg={inst}`")); diag.note("see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration"); @@ -266,9 +266,9 @@ pub(super) fn unexpected_cfg_value( diag.help("consider defining some features in `Cargo.toml`"); } } else if !is_cfg_a_well_know_name { - diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo:rustc-check-cfg={inst}\");` to the top of a `build.rs`")); + diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo::rustc-check-cfg={inst}\");` to the top of the `build.rs`")); } - diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration"); + diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration"); } else { if !is_cfg_a_well_know_name { diag.help(format!("to expect this configuration use `--check-cfg={inst}`")); diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 8878310d6e9..9d58d301e2b 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -49,12 +49,6 @@ passes_attr_crate_level = passes_attr_only_in_functions = `{$attr}` attribute can only be used on functions -passes_attr_only_on_main = - `{$attr}` attribute can only be used on `fn main()` - -passes_attr_only_on_root_main = - `{$attr}` attribute can only be used on root `fn main()` - passes_both_ffi_const_and_pure = `#[ffi_const]` function cannot be `#[ffi_pure]` diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index d52092f2aa9..b43c8282db1 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -18,10 +18,10 @@ use crate::errors::{ struct EntryContext<'tcx> { tcx: TyCtxt<'tcx>, - /// The function that has attribute named `main`. - attr_main_fn: Option<(LocalDefId, Span)>, + /// The function has the `#[rustc_main]` attribute. + rustc_main_fn: Option<(LocalDefId, Span)>, - /// The function that has the attribute 'start' on it. + /// The function that has the attribute `#[start]` on it. start_fn: Option<(LocalDefId, Span)>, /// The functions that one might think are `main` but aren't, e.g. @@ -42,10 +42,10 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> { } let mut ctxt = - EntryContext { tcx, attr_main_fn: None, start_fn: None, non_main_fns: Vec::new() }; + EntryContext { tcx, rustc_main_fn: None, start_fn: None, non_main_fns: Vec::new() }; for id in tcx.hir().items() { - find_item(id, &mut ctxt); + check_and_search_item(id, &mut ctxt); } configure_main(tcx, &ctxt) @@ -56,7 +56,16 @@ fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Opti attr::find_by_name(attrs, sym).map(|attr| attr.span) } -fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { +fn check_and_search_item(id: ItemId, ctxt: &mut EntryContext<'_>) { + if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) { + for attr in [sym::start, sym::rustc_main] { + if let Some(span) = attr_span_by_symbol(ctxt, id, attr) { + ctxt.tcx.dcx().emit_err(AttrOnlyInFunctions { span, attr }); + } + } + return; + } + let at_root = ctxt.tcx.opt_local_parent(id.owner_id.def_id) == Some(CRATE_DEF_ID); let attrs = ctxt.tcx.hir().attrs(id.hir_id()); @@ -65,26 +74,20 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { at_root, ctxt.tcx.opt_item_name(id.owner_id.to_def_id()), ); + match entry_point_type { - EntryPointType::None => (), - _ if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) => { - for attr in [sym::start, sym::rustc_main] { - if let Some(span) = attr_span_by_symbol(ctxt, id, attr) { - ctxt.tcx.dcx().emit_err(AttrOnlyInFunctions { span, attr }); - } - } - } - EntryPointType::MainNamed => (), + EntryPointType::None => {} + EntryPointType::MainNamed => {} EntryPointType::OtherMain => { ctxt.non_main_fns.push(ctxt.tcx.def_span(id.owner_id)); } EntryPointType::RustcMainAttr => { - if ctxt.attr_main_fn.is_none() { - ctxt.attr_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id))); + if ctxt.rustc_main_fn.is_none() { + ctxt.rustc_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id))); } else { ctxt.tcx.dcx().emit_err(MultipleRustcMain { span: ctxt.tcx.def_span(id.owner_id.to_def_id()), - first: ctxt.attr_main_fn.unwrap().1, + first: ctxt.rustc_main_fn.unwrap().1, additional: ctxt.tcx.def_span(id.owner_id.to_def_id()), }); } @@ -107,10 +110,11 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, EntryFnType)> { if let Some((def_id, _)) = visitor.start_fn { Some((def_id.to_def_id(), EntryFnType::Start)) - } else if let Some((local_def_id, _)) = visitor.attr_main_fn { + } else if let Some((local_def_id, _)) = visitor.rustc_main_fn { let def_id = local_def_id.to_def_id(); Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx) })) } else { + // The actual resolution of main happens in the resolver, this here if let Some(main_def) = tcx.resolutions(()).main_def && let Some(def_id) = main_def.opt_fn_def_id() { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 743faf54560..65cad82cc8c 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1207,22 +1207,6 @@ pub struct NakedFunctionsMustUseNoreturn { } #[derive(Diagnostic)] -#[diag(passes_attr_only_on_main)] -pub struct AttrOnlyOnMain { - #[primary_span] - pub span: Span, - pub attr: Symbol, -} - -#[derive(Diagnostic)] -#[diag(passes_attr_only_on_root_main)] -pub struct AttrOnlyOnRootMain { - #[primary_span] - pub span: Span, - pub attr: Symbol, -} - -#[derive(Diagnostic)] #[diag(passes_attr_only_in_functions)] pub struct AttrOnlyInFunctions { #[primary_span] diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 796222129f1..fd4b5805f02 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -11,6 +11,7 @@ use rustc_infer::traits::{ }; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, TyCtxt}; +use rustc_span::symbol::sym; use super::eval_ctxt::GenerateProofTree; use super::inspect::{ProofTreeInferCtxtExt, ProofTreeVisitor}; @@ -137,7 +138,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { .collect(); errors.extend(self.obligations.overflowed.drain(..).map(|obligation| FulfillmentError { - obligation: find_best_leaf_obligation(infcx, &obligation), + obligation: find_best_leaf_obligation(infcx, &obligation, true), code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) }, root_obligation: obligation, })); @@ -198,7 +199,7 @@ fn fulfillment_error_for_no_solution<'tcx>( infcx: &InferCtxt<'tcx>, root_obligation: PredicateObligation<'tcx>, ) -> FulfillmentError<'tcx> { - let obligation = find_best_leaf_obligation(infcx, &root_obligation); + let obligation = find_best_leaf_obligation(infcx, &root_obligation, false); let code = match obligation.predicate.kind().skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => { @@ -266,7 +267,7 @@ fn fulfillment_error_for_stalled<'tcx>( }); FulfillmentError { - obligation: find_best_leaf_obligation(infcx, &obligation), + obligation: find_best_leaf_obligation(infcx, &obligation, true), code, root_obligation: obligation, } @@ -275,12 +276,13 @@ fn fulfillment_error_for_stalled<'tcx>( fn find_best_leaf_obligation<'tcx>( infcx: &InferCtxt<'tcx>, obligation: &PredicateObligation<'tcx>, + consider_ambiguities: bool, ) -> PredicateObligation<'tcx> { let obligation = infcx.resolve_vars_if_possible(obligation.clone()); infcx .visit_proof_tree( obligation.clone().into(), - &mut BestObligation { obligation: obligation.clone() }, + &mut BestObligation { obligation: obligation.clone(), consider_ambiguities }, ) .break_value() .unwrap_or(obligation) @@ -288,6 +290,7 @@ fn find_best_leaf_obligation<'tcx>( struct BestObligation<'tcx> { obligation: PredicateObligation<'tcx>, + consider_ambiguities: bool, } impl<'tcx> BestObligation<'tcx> { @@ -320,6 +323,14 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { return ControlFlow::Break(self.obligation.clone()); }; + // Don't walk into impls that have `do_not_recommend`. + if let ProbeKind::TraitCandidate { source: CandidateSource::Impl(impl_def_id), result: _ } = + candidate.kind() + && goal.infcx().tcx.has_attr(impl_def_id, sym::do_not_recommend) + { + return ControlFlow::Break(self.obligation.clone()); + } + // FIXME: Could we extract a trait ref from a projection here too? // FIXME: Also, what about considering >1 layer up the stack? May be necessary // for normalizes-to. @@ -355,11 +366,11 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { } } - // Skip nested goals that hold. - //FIXME: We should change the max allowed certainty based on if we're - // visiting an ambiguity or error obligation. - if matches!(nested_goal.result(), Ok(Certainty::Yes)) { - continue; + // Skip nested goals that aren't the *reason* for our goal's failure. + match self.consider_ambiguities { + true if matches!(nested_goal.result(), Ok(Certainty::Maybe(_))) => {} + false if matches!(nested_goal.result(), Err(_)) => {} + _ => continue, } self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?; diff --git a/config.example.toml b/config.example.toml index 5c1fac7672a..3b76952504f 100644 --- a/config.example.toml +++ b/config.example.toml @@ -254,6 +254,10 @@ # executing the debuginfo test suite. #gdb = "gdb" +# The path to (or name of) the LLDB executable to use. This is only used for +# executing the debuginfo test suite. +#lldb = "lldb" + # The node.js executable to use. Note that this is only used for the emscripten # target when running tests, otherwise this can be omitted. #nodejs = "node" diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index de766a4b977..ed7bcec89b9 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -9,7 +9,7 @@ use crate::cmp::Ordering::{self, Equal, Greater, Less}; use crate::fmt; use crate::hint; -use crate::intrinsics::exact_div; +use crate::intrinsics::{exact_div, unchecked_sub}; use crate::mem::{self, SizedTypeProperties}; use crate::num::NonZero; use crate::ops::{Bound, OneSidedRange, Range, RangeBounds}; @@ -1983,7 +1983,7 @@ impl<T> [T] { ); // SAFETY: Caller has to check that `0 <= mid <= self.len()` - unsafe { (from_raw_parts(ptr, mid), from_raw_parts(ptr.add(mid), len - mid)) } + unsafe { (from_raw_parts(ptr, mid), from_raw_parts(ptr.add(mid), unchecked_sub(len, mid))) } } /// Divides one mutable slice into two at an index, without doing bounds checking. @@ -2035,7 +2035,12 @@ impl<T> [T] { // // `[ptr; mid]` and `[mid; len]` are not overlapping, so returning a mutable reference // is fine. - unsafe { (from_raw_parts_mut(ptr, mid), from_raw_parts_mut(ptr.add(mid), len - mid)) } + unsafe { + ( + from_raw_parts_mut(ptr, mid), + from_raw_parts_mut(ptr.add(mid), unchecked_sub(len, mid)), + ) + } } /// Divides one slice into two at an index, returning `None` if the slice is diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index f6680b211c7..37492e9efab 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -364,6 +364,27 @@ where self.pos += n as u64; Ok(()) } + + fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { + let content = self.remaining_slice(); + let len = content.len(); + buf.try_reserve(len)?; + buf.extend_from_slice(content); + self.pos += len as u64; + + Ok(len) + } + + fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { + let content = + crate::str::from_utf8(self.remaining_slice()).map_err(|_| io::Error::INVALID_UTF8)?; + let len = content.len(); + buf.try_reserve(len)?; + buf.push_str(content); + self.pos += len as u64; + + Ok(len) + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index dd7e0725176..46f04c7cd39 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -329,8 +329,9 @@ impl Read for &[u8] { #[inline] fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { let content = str::from_utf8(self).map_err(|_| io::Error::INVALID_UTF8)?; - buf.push_str(content); let len = self.len(); + buf.try_reserve(len)?; + buf.push_str(content); *self = &self[len..]; Ok(len) } @@ -473,14 +474,8 @@ impl<A: Allocator> Read for VecDeque<u8, A> { #[inline] fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { - // We have to use a single contiguous slice because the `VecDequeue` might be split in the - // middle of an UTF-8 character. - let len = self.len(); - let content = self.make_contiguous(); - let string = str::from_utf8(content).map_err(|_| io::Error::INVALID_UTF8)?; - buf.push_str(string); - self.clear(); - Ok(len) + // SAFETY: We only append to the buffer + unsafe { io::append_to_string(buf, |buf| self.read_to_end(buf)) } } } diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index a3fdcdc2d07..af055152cbe 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -384,7 +384,10 @@ where { let mut g = Guard { len: buf.len(), buf: buf.as_mut_vec() }; let ret = f(g.buf); - if str::from_utf8(&g.buf[g.len..]).is_err() { + + // SAFETY: the caller promises to only append data to `buf` + let appended = g.buf.get_unchecked(g.len..); + if str::from_utf8(appended).is_err() { ret.and_then(|_| Err(Error::INVALID_UTF8)) } else { g.len = g.buf.len(); diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 4a73a9be88b..d1848224251 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -486,6 +486,10 @@ impl Read for ChildStderr { fn is_read_vectored(&self) -> bool { self.inner.is_read_vectored() } + + fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { + self.inner.read_to_end(buf) + } } impl AsInner<AnonPipe> for ChildStderr { diff --git a/rustfmt.toml b/rustfmt.toml index 67219b15d20..850d01ea7cb 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -13,6 +13,12 @@ ignore = [ # tests for now are not formatted, as they are sometimes pretty-printing constrained # (and generally rustfmt can move around comments in UI-testing incompatible ways) + "/tests/*", + + # but we still want to format rmake.rs files in tests/run-make/ so we need to do this + # dance to avoid the parent directory from being excluded + "!/tests/run-make/", + "/tests/run-make/*/*.rs", "!/tests/run-make/*/rmake.rs", # do not format submodules diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index c7a513d0890..e9675e20452 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -33,9 +33,9 @@ path = "src/bin/sccache-plus-cl.rs" test = false [dependencies] -# Most of the time updating these dependencies requires modifications -# to the bootstrap codebase; otherwise, some targets will fail. That's -# why these dependencies are explicitly pinned. +# Most of the time updating these dependencies requires modifications to the +# bootstrap codebase(e.g., https://github.com/rust-lang/rust/issues/124565); +# otherwise, some targets will fail. That's why these dependencies are explicitly pinned. cc = "=1.0.73" cmake = "=0.1.48" diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 9a585a39e1e..360bd3840d4 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1892,15 +1892,16 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the .to_string() }) }; - let lldb_exe = "lldb"; - let lldb_version = Command::new(lldb_exe) + + let lldb_exe = builder.config.lldb.clone().unwrap_or_else(|| PathBuf::from("lldb")); + let lldb_version = Command::new(&lldb_exe) .arg("--version") .output() .map(|output| String::from_utf8_lossy(&output.stdout).to_string()) .ok(); if let Some(ref vers) = lldb_version { cmd.arg("--lldb-version").arg(vers); - let lldb_python_dir = run(Command::new(lldb_exe).arg("-P")).ok(); + let lldb_python_dir = run(Command::new(&lldb_exe).arg("-P")).ok(); if let Some(ref dir) = lldb_python_dir { cmd.arg("--lldb-python-dir").arg(dir); } diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index ed45bc30362..0167c51fc7e 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -329,6 +329,7 @@ pub struct Config { pub nodejs: Option<PathBuf>, pub npm: Option<PathBuf>, pub gdb: Option<PathBuf>, + pub lldb: Option<PathBuf>, pub python: Option<PathBuf>, pub reuse: Option<PathBuf>, pub cargo_native_static: bool, @@ -834,6 +835,7 @@ define_config! { docs_minification: Option<bool> = "docs-minification", submodules: Option<bool> = "submodules", gdb: Option<String> = "gdb", + lldb: Option<String> = "lldb", nodejs: Option<String> = "nodejs", npm: Option<String> = "npm", python: Option<String> = "python", @@ -1410,6 +1412,7 @@ impl Config { docs_minification, submodules, gdb, + lldb, nodejs, npm, python, @@ -1502,6 +1505,7 @@ impl Config { config.nodejs = nodejs.map(PathBuf::from); config.npm = npm.map(PathBuf::from); config.gdb = gdb.map(PathBuf::from); + config.lldb = lldb.map(PathBuf::from); config.python = python.map(PathBuf::from); config.reuse = reuse.map(PathBuf::from); config.submodules = submodules; diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index db3df598a0c..c3a03693f71 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -175,4 +175,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Warning, summary: "The deprecated field `changelog-seen` has been removed. Using that field in `config.toml` from now on will result in breakage.", }, + ChangeInfo { + change_id: 124501, + severity: ChangeSeverity::Info, + summary: "New option `build.lldb` that will override the default lldb binary path used in debuginfo tests", + }, ]; diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index fcc507b572c..22dcb808c74 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -50,39 +50,35 @@ fi CACHE_DOMAIN="${CACHE_DOMAIN:-ci-caches.rust-lang.org}" if [ -f "$docker_dir/$image/Dockerfile" ]; then - if isCI; then - hash_key=/tmp/.docker-hash-key.txt - rm -f "${hash_key}" - echo $image >> $hash_key - - cat "$docker_dir/$image/Dockerfile" >> $hash_key - # Look for all source files involves in the COPY command - copied_files=/tmp/.docker-copied-files.txt - rm -f "$copied_files" - for i in $(sed -n -e '/^COPY --from=/! s/^COPY \(.*\) .*$/\1/p' \ - "$docker_dir/$image/Dockerfile"); do - # List the file names - find "$script_dir/$i" -type f >> $copied_files - done - # Sort the file names and cat the content into the hash key - sort $copied_files | xargs cat >> $hash_key - - # Include the architecture in the hash key, since our Linux CI does not - # only run in x86_64 machines. - uname -m >> $hash_key - - docker --version >> $hash_key - - # Include cache version. Can be used to manually bust the Docker cache. - echo "2" >> $hash_key - - echo "Image input" - cat $hash_key - - cksum=$(sha512sum $hash_key | \ - awk '{print $1}') - echo "Image input checksum ${cksum}" - fi + hash_key=/tmp/.docker-hash-key.txt + rm -f "${hash_key}" + echo $image >> $hash_key + + cat "$docker_dir/$image/Dockerfile" >> $hash_key + # Look for all source files involves in the COPY command + copied_files=/tmp/.docker-copied-files.txt + rm -f "$copied_files" + for i in $(sed -n -e '/^COPY --from=/! s/^COPY \(.*\) .*$/\1/p' \ + "$docker_dir/$image/Dockerfile"); do + # List the file names + find "$script_dir/$i" -type f >> $copied_files + done + # Sort the file names and cat the content into the hash key + sort $copied_files | xargs cat >> $hash_key + + # Include the architecture in the hash key, since our Linux CI does not + # only run in x86_64 machines. + uname -m >> $hash_key + + # Include cache version. Can be used to manually bust the Docker cache. + echo "2" >> $hash_key + + echo "Image input" + cat $hash_key + + cksum=$(sha512sum $hash_key | \ + awk '{print $1}') + echo "Image input checksum ${cksum}" dockerfile="$docker_dir/$image/Dockerfile" if [ -x /usr/bin/cygpath ]; then @@ -105,10 +101,18 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then # It seems that it cannot be the same as $IMAGE_TAG, otherwise it overwrites the cache CACHE_IMAGE_TAG=${REGISTRY}/${REGISTRY_USERNAME}/rust-ci-cache:${cksum} - # On non-CI jobs, we don't do any caching. + # On non-CI jobs, we try to download a pre-built image from the rust-lang-ci + # ghcr.io registry. If it is not possible, we fall back to building the image + # locally. if ! isCI; then - retry docker build --rm -t rust-ci -f "$dockerfile" "$context" + if docker pull "${IMAGE_TAG}"; then + echo "Downloaded Docker image from CI" + docker tag "${IMAGE_TAG}" rust-ci + else + echo "Building local Docker image" + retry docker build --rm -t rust-ci -f "$dockerfile" "$context" + fi # On PR CI jobs, we don't have permissions to write to the registry cache, # but we can still read from it. elif [[ "$PR_CI_JOB" == "1" ]]; diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index f47c84842b1..3b1d7687d02 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -95,6 +95,7 @@ pub use rustc_const_eval::interpret::*; #[doc(no_inline)] pub use rustc_const_eval::interpret::{self, AllocMap, PlaceTy, Provenance as _}; +pub use crate::shims::EmulateItemResult; pub use crate::shims::env::{EnvVars, EvalContextExt as _}; pub use crate::shims::foreign_items::{DynSym, EvalContextExt as _}; pub use crate::shims::intrinsics::EvalContextExt as _; diff --git a/src/tools/miri/src/shims/alloc.rs b/src/tools/miri/src/shims/alloc.rs index b5ae06c2a49..79531598c00 100644 --- a/src/tools/miri/src/shims/alloc.rs +++ b/src/tools/miri/src/shims/alloc.rs @@ -4,7 +4,6 @@ use rustc_ast::expand::allocator::AllocatorKind; use rustc_target::abi::{Align, Size}; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; /// Check some basic requirements for this allocation request: /// non-zero size, power-of-two alignment. @@ -55,12 +54,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn emulate_allocator( &mut self, default: impl FnOnce(&mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); let Some(allocator_kind) = this.tcx.allocator_kind(()) else { // in real code, this symbol does not exist without an allocator - return Ok(EmulateForeignItemResult::NotSupported); + return Ok(EmulateItemResult::NotSupported); }; match allocator_kind { @@ -70,11 +69,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // and not execute any Miri shim. Somewhat unintuitively doing so is done // by returning `NotSupported`, which triggers the `lookup_exported_symbol` // fallback case in `emulate_foreign_item`. - return Ok(EmulateForeignItemResult::NotSupported); + return Ok(EmulateItemResult::NotSupported); } AllocatorKind::Default => { default(this)?; - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } } diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 636361148a4..8a38c6c11a8 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -28,16 +28,6 @@ impl DynSym { } } -/// Returned by `emulate_foreign_item_inner`. -pub enum EmulateForeignItemResult { - /// The caller is expected to jump to the return block. - NeedsJumping, - /// Jumping has already been taken care of. - AlreadyJumped, - /// The item is not supported. - NotSupported, -} - impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// Emulates calling a foreign item, failing if the item is not supported. @@ -58,84 +48,47 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); let tcx = this.tcx.tcx; - // First: functions that diverge. - let ret = match ret { - None => - match link_name.as_str() { - "miri_start_unwind" => { - // `check_shim` happens inside `handle_miri_start_unwind`. - this.handle_miri_start_unwind(abi, link_name, args, unwind)?; - return Ok(None); - } - // This matches calls to the foreign item `panic_impl`. - // The implementation is provided by the function with the `#[panic_handler]` attribute. - "panic_impl" => { - // We don't use `check_shim` here because we are just forwarding to the lang - // item. Argument count checking will be performed when the returned `Body` is - // called. - this.check_abi_and_shim_symbol_clash(abi, Abi::Rust, link_name)?; - let panic_impl_id = tcx.lang_items().panic_impl().unwrap(); - let panic_impl_instance = ty::Instance::mono(tcx, panic_impl_id); - return Ok(Some(( - this.load_mir(panic_impl_instance.def, None)?, - panic_impl_instance, - ))); - } - "__rust_alloc_error_handler" => { - // Forward to the right symbol that implements this function. - let Some(handler_kind) = this.tcx.alloc_error_handler_kind(()) else { - // in real code, this symbol does not exist without an allocator - throw_unsup_format!( - "`__rust_alloc_error_handler` cannot be called when no alloc error handler is set" - ); - }; - let name = alloc_error_handler_name(handler_kind); - let handler = this - .lookup_exported_symbol(Symbol::intern(name))? - .expect("missing alloc error handler symbol"); - return Ok(Some(handler)); - } - #[rustfmt::skip] - | "exit" - | "ExitProcess" - => { - let exp_abi = if link_name.as_str() == "exit" { - Abi::C { unwind: false } - } else { - Abi::System { unwind: false } - }; - let [code] = this.check_shim(abi, exp_abi, link_name, args)?; - // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway - let code = this.read_scalar(code)?.to_i32()?; - throw_machine_stop!(TerminationInfo::Exit { code: code.into(), leak_check: false }); - } - "abort" => { - let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - throw_machine_stop!(TerminationInfo::Abort( - "the program aborted execution".to_owned() - )) - } - _ => { - if let Some(body) = this.lookup_exported_symbol(link_name)? { - return Ok(Some(body)); - } - this.handle_unsupported(format!( - "can't call (diverging) foreign function: {link_name}" - ))?; - return Ok(None); - } - }, - Some(p) => p, - }; + // Some shims forward to other MIR bodies. + match link_name.as_str() { + // This matches calls to the foreign item `panic_impl`. + // The implementation is provided by the function with the `#[panic_handler]` attribute. + "panic_impl" => { + // We don't use `check_shim` here because we are just forwarding to the lang + // item. Argument count checking will be performed when the returned `Body` is + // called. + this.check_abi_and_shim_symbol_clash(abi, Abi::Rust, link_name)?; + let panic_impl_id = tcx.lang_items().panic_impl().unwrap(); + let panic_impl_instance = ty::Instance::mono(tcx, panic_impl_id); + return Ok(Some(( + this.load_mir(panic_impl_instance.def, None)?, + panic_impl_instance, + ))); + } + "__rust_alloc_error_handler" => { + // Forward to the right symbol that implements this function. + let Some(handler_kind) = this.tcx.alloc_error_handler_kind(()) else { + // in real code, this symbol does not exist without an allocator + throw_unsup_format!( + "`__rust_alloc_error_handler` cannot be called when no alloc error handler is set" + ); + }; + let name = alloc_error_handler_name(handler_kind); + let handler = this + .lookup_exported_symbol(Symbol::intern(name))? + .expect("missing alloc error handler symbol"); + return Ok(Some(handler)); + } + _ => {} + } - // Second: functions that return immediately. - match this.emulate_foreign_item_inner(link_name, abi, args, dest)? { - EmulateForeignItemResult::NeedsJumping => { + // The rest either implements the logic, or falls back to `lookup_exported_symbol`. + match this.emulate_foreign_item_inner(link_name, abi, args, dest, unwind)? { + EmulateItemResult::NeedsJumping => { trace!("{:?}", this.dump_place(&dest.clone().into())); - this.go_to_block(ret); + this.return_to_block(ret)?; } - EmulateForeignItemResult::AlreadyJumped => (), - EmulateForeignItemResult::NotSupported => { + EmulateItemResult::AlreadyJumped => (), + EmulateItemResult::NotSupported => { if let Some(body) = this.lookup_exported_symbol(link_name)? { return Ok(Some(body)); } @@ -243,7 +196,8 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + unwind: mir::UnwindAction, + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); // First deal with any external C functions in linked .so file. @@ -254,7 +208,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // by the specified `.so` file; we should continue and check if it corresponds to // a provided shim. if this.call_external_c_fct(link_name, dest, args)? { - return Ok(EmulateForeignItemResult::NeedsJumping); + return Ok(EmulateItemResult::NeedsJumping); } } @@ -298,6 +252,11 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // shim, add it to the corresponding submodule. match link_name.as_str() { // Miri-specific extern functions + "miri_start_unwind" => { + // `check_shim` happens inside `handle_miri_start_unwind`. + this.handle_miri_start_unwind(abi, link_name, args, unwind)?; + return Ok(EmulateItemResult::AlreadyJumped); + } "miri_run_provenance_gc" => { let [] = this.check_shim(abi, Abi::Rust, link_name, args)?; this.run_provenance_gc(); @@ -362,29 +321,24 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Return value: 0 on success, otherwise the size it would have needed. this.write_int(if success { 0 } else { needed_size }, dest)?; } - // Obtains the size of a Miri backtrace. See the README for details. "miri_backtrace_size" => { this.handle_miri_backtrace_size(abi, link_name, args, dest)?; } - // Obtains a Miri backtrace. See the README for details. "miri_get_backtrace" => { // `check_shim` happens inside `handle_miri_get_backtrace`. this.handle_miri_get_backtrace(abi, link_name, args, dest)?; } - // Resolves a Miri backtrace frame. See the README for details. "miri_resolve_frame" => { // `check_shim` happens inside `handle_miri_resolve_frame`. this.handle_miri_resolve_frame(abi, link_name, args, dest)?; } - // Writes the function and file names of a Miri backtrace frame into a user provided buffer. See the README for details. "miri_resolve_frame_names" => { this.handle_miri_resolve_frame_names(abi, link_name, args)?; } - // Writes some bytes to the interpreter's stdout/stderr. See the // README for details. "miri_write_to_stdout" | "miri_write_to_stderr" => { @@ -398,7 +352,6 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => unreachable!(), }; } - // Promises that a pointer has a given symbolic alignment. "miri_promise_symbolic_alignment" => { use rustc_target::abi::AlignFromBytesError; @@ -442,6 +395,25 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } + // Aborting the process. + "exit" | "ExitProcess" => { + let exp_abi = if link_name.as_str() == "exit" { + Abi::C { unwind: false } + } else { + Abi::System { unwind: false } + }; + let [code] = this.check_shim(abi, exp_abi, link_name, args)?; + // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway + let code = this.read_scalar(code)?.to_i32()?; + throw_machine_stop!(TerminationInfo::Exit { code: code.into(), leak_check: false }); + } + "abort" => { + let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + throw_machine_stop!(TerminationInfo::Abort( + "the program aborted execution".to_owned() + )) + } + // Standard C allocation "malloc" => { let [size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -504,7 +476,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "__rust_alloc" => return this.emulate_allocator(default), "miri_alloc" => { default(this)?; - return Ok(EmulateForeignItemResult::NeedsJumping); + return Ok(EmulateItemResult::NeedsJumping); } _ => unreachable!(), } @@ -564,7 +536,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } "miri_dealloc" => { default(this)?; - return Ok(EmulateForeignItemResult::NeedsJumping); + return Ok(EmulateItemResult::NeedsJumping); } _ => unreachable!(), } @@ -966,11 +938,11 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_inner( this, link_name, abi, args, dest, ), - _ => Ok(EmulateForeignItemResult::NotSupported), + _ => Ok(EmulateItemResult::NotSupported), }, }; // We only fall through to here if we did *not* hit the `_` arm above, // i.e., if we actually emulated the function with one of the shims. - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/intrinsics/atomic.rs b/src/tools/miri/src/shims/intrinsics/atomic.rs index 4c5e2192e5c..40f6b8a64ef 100644 --- a/src/tools/miri/src/shims/intrinsics/atomic.rs +++ b/src/tools/miri/src/shims/intrinsics/atomic.rs @@ -20,7 +20,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { intrinsic_name: &str, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, bool> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); let intrinsic_structure: Vec<_> = intrinsic_name.split('_').collect(); @@ -114,9 +114,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.atomic_rmw_op(args, dest, AtomicOp::Max, rw_ord(ord)?)?; } - _ => return Ok(false), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(true) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs index 2bf6980200f..974943432aa 100644 --- a/src/tools/miri/src/shims/intrinsics/mod.rs +++ b/src/tools/miri/src/shims/intrinsics/mod.rs @@ -10,8 +10,8 @@ use rustc_middle::{ mir, ty::{self, FloatTy}, }; -use rustc_target::abi::Size; use rustc_span::{sym, Symbol}; +use rustc_target::abi::Size; use crate::*; use atomic::EvalContextExt as _; @@ -37,51 +37,38 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let intrinsic_name = this.tcx.item_name(instance.def_id()); let intrinsic_name = intrinsic_name.as_str(); - // Handle intrinsics without return place. - match intrinsic_name { - "abort" => { - throw_machine_stop!(TerminationInfo::Abort( - "the program aborted execution".to_owned() - )) - } - _ => {} - } - - // All remaining supported intrinsics have a return place. - let ret = match ret { - // FIXME: add fallback body support once we actually have a diverging intrinsic with a fallback body - None => throw_unsup_format!("unimplemented (diverging) intrinsic: `{intrinsic_name}`"), - Some(p) => p, - }; - - // Some intrinsics are special and need the "ret". - match intrinsic_name { - "catch_unwind" => { - this.handle_catch_unwind(args, dest, ret)?; - return Ok(None); - } - _ => {} - } - - // The rest jumps to `ret` immediately. - if !this.emulate_intrinsic_by_name(intrinsic_name, instance.args, args, dest)? { - // We haven't handled the intrinsic, let's see if we can use a fallback body. - if this.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden { - throw_unsup_format!("unimplemented intrinsic: `{intrinsic_name}`") + match this.emulate_intrinsic_by_name(intrinsic_name, instance.args, args, dest, ret)? { + EmulateItemResult::NotSupported => { + // We haven't handled the intrinsic, let's see if we can use a fallback body. + if this.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden { + throw_unsup_format!("unimplemented intrinsic: `{intrinsic_name}`") + } + let intrinsic_fallback_checks_ub = Symbol::intern("intrinsic_fallback_checks_ub"); + if this + .tcx + .get_attrs_by_path( + instance.def_id(), + &[sym::miri, intrinsic_fallback_checks_ub], + ) + .next() + .is_none() + { + throw_unsup_format!( + "miri can only use intrinsic fallback bodies that check UB. After verifying that `{intrinsic_name}` does so, add the `#[miri::intrinsic_fallback_checks_ub]` attribute to it; also ping @rust-lang/miri when you do that" + ); + } + Ok(Some(ty::Instance { + def: ty::InstanceDef::Item(instance.def_id()), + args: instance.args, + })) } - let intrinsic_fallback_checks_ub = Symbol::intern("intrinsic_fallback_checks_ub"); - if this.tcx.get_attrs_by_path(instance.def_id(), &[sym::miri, intrinsic_fallback_checks_ub]).next().is_none() { - throw_unsup_format!("miri can only use intrinsic fallback bodies that check UB. After verifying that `{intrinsic_name}` does so, add the `#[miri::intrinsic_fallback_checks_ub]` attribute to it; also ping @rust-lang/miri when you do that"); + EmulateItemResult::NeedsJumping => { + trace!("{:?}", this.dump_place(&dest.clone().into())); + this.return_to_block(ret)?; + Ok(None) } - return Ok(Some(ty::Instance { - def: ty::InstanceDef::Item(instance.def_id()), - args: instance.args, - })) + EmulateItemResult::AlreadyJumped => Ok(None), } - - trace!("{:?}", this.dump_place(&dest.clone().into())); - this.go_to_block(ret); - Ok(None) } /// Emulates a Miri-supported intrinsic (not supported by the core engine). @@ -92,7 +79,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { generic_args: ty::GenericArgsRef<'tcx>, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, bool> { + ret: Option<mir::BasicBlock>, + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); if let Some(name) = intrinsic_name.strip_prefix("atomic_") { @@ -103,6 +91,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } match intrinsic_name { + "abort" => { + throw_machine_stop!(TerminationInfo::Abort( + "the program aborted execution".to_owned() + )); + } + "catch_unwind" => { + this.handle_catch_unwind(args, dest, ret)?; + // THis pushed a stack frame, don't jump to `ret`. + return Ok(EmulateItemResult::AlreadyJumped); + } + // Raw memory accesses "volatile_load" => { let [place] = check_arg_count(args)?; @@ -426,9 +425,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { throw_machine_stop!(TerminationInfo::Abort(format!("trace/breakpoint trap"))) } - _ => return Ok(false), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(true) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs index dca4c4ea5ad..c7de587443a 100644 --- a/src/tools/miri/src/shims/intrinsics/simd.rs +++ b/src/tools/miri/src/shims/intrinsics/simd.rs @@ -23,7 +23,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { generic_args: ty::GenericArgsRef<'tcx>, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, bool> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); match intrinsic_name { #[rustfmt::skip] @@ -744,9 +744,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - _ => return Ok(false), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(true) + Ok(EmulateItemResult::NeedsJumping) } fn fminmax_op( diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs index 85c9a202f7d..975efe29b4b 100644 --- a/src/tools/miri/src/shims/mod.rs +++ b/src/tools/miri/src/shims/mod.rs @@ -16,3 +16,13 @@ pub mod os_str; pub mod panic; pub mod time; pub mod tls; + +/// What needs to be done after emulating an item (a shim or an intrinsic) is done. +pub enum EmulateItemResult { + /// The caller is expected to jump to the return block. + NeedsJumping, + /// Jumping has already been taken care of. + AlreadyJumped, + /// The item is not supported. + NotSupported, +} diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs index bb31ef733cf..4444d297469 100644 --- a/src/tools/miri/src/shims/panic.rs +++ b/src/tools/miri/src/shims/panic.rs @@ -30,7 +30,7 @@ pub struct CatchUnwindData<'tcx> { /// The return place from the original call to `try`. dest: MPlaceTy<'tcx, Provenance>, /// The return block from the original call to `try`. - ret: mir::BasicBlock, + ret: Option<mir::BasicBlock>, } impl VisitProvenance for CatchUnwindData<'_> { @@ -73,7 +73,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { &mut self, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ret: mir::BasicBlock, + ret: Option<mir::BasicBlock>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); @@ -103,7 +103,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { &[data.into()], None, // Directly return to caller. - StackPopCleanup::Goto { ret: Some(ret), unwind: mir::UnwindAction::Continue }, + StackPopCleanup::Goto { ret, unwind: mir::UnwindAction::Continue }, )?; // We ourselves will return `0`, eventually (will be overwritten if we catch a panic). @@ -155,7 +155,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { None, // Directly return to caller of `try`. StackPopCleanup::Goto { - ret: Some(catch_unwind.ret), + ret: catch_unwind.ret, unwind: mir::UnwindAction::Continue, }, )?; diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index bd299aaa125..7f6a3ba0887 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -9,7 +9,6 @@ use rustc_target::spec::abi::Abi; use crate::shims::alloc::EvalContextExt as _; use crate::shims::unix::*; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; use shims::unix::freebsd::foreign_items as freebsd; use shims::unix::linux::foreign_items as linux; @@ -43,7 +42,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. @@ -750,11 +749,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "freebsd" => freebsd::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), "linux" => linux::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), "macos" => macos::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), - _ => Ok(EmulateForeignItemResult::NotSupported), + _ => Ok(EmulateItemResult::NotSupported), }; } }; - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index ffb583123d4..1e0e7d16320 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -3,7 +3,6 @@ use rustc_target::spec::abi::Abi; use crate::shims::unix::*; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; pub fn is_dyn_sym(_name: &str) -> bool { false @@ -17,7 +16,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); match link_name.as_str() { // Threading @@ -97,8 +96,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 497e8bee70e..dd4ec8cfaa7 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -5,7 +5,6 @@ use crate::machine::SIGRTMAX; use crate::machine::SIGRTMIN; use crate::shims::unix::*; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; use shims::unix::linux::epoll::EvalContextExt as _; use shims::unix::linux::eventfd::EvalContextExt as _; use shims::unix::linux::mem::EvalContextExt as _; @@ -23,7 +22,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. @@ -156,7 +155,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } id => { this.handle_unsupported(format!("can't execute syscall with ID {id}"))?; - return Ok(EmulateForeignItemResult::AlreadyJumped); + return Ok(EmulateItemResult::AlreadyJumped); } } } @@ -204,10 +203,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_null(dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), }; - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index 66a8dce753f..912623b7225 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -3,7 +3,6 @@ use rustc_target::spec::abi::Abi; use crate::shims::unix::*; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; pub fn is_dyn_sym(_name: &str) -> bool { false @@ -17,7 +16,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. @@ -175,9 +174,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(res, dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), }; - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index e8ae80261c6..08aee04254b 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -12,7 +12,6 @@ use crate::shims::alloc::EvalContextExt as _; use crate::shims::os_str::bytes_to_os_str; use crate::shims::windows::*; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; use shims::windows::handle::{Handle, PseudoHandle}; fn is_dyn_sym(name: &str) -> bool { @@ -86,7 +85,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. @@ -721,9 +720,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_null(dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/aesni.rs b/src/tools/miri/src/shims/x86/aesni.rs index 6c090d877ea..8dc3748a12d 100644 --- a/src/tools/miri/src/shims/x86/aesni.rs +++ b/src/tools/miri/src/shims/x86/aesni.rs @@ -4,7 +4,6 @@ use rustc_span::Symbol; use rustc_target::spec::abi::Abi; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -16,7 +15,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "aes")?; // Prefix should have already been checked. @@ -126,9 +125,9 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: } // TODO: Implement the `llvm.x86.aesni.aeskeygenassist` when possible // with an external crate. - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/avx.rs b/src/tools/miri/src/shims/x86/avx.rs index 41c20d768f7..86ef180a448 100644 --- a/src/tools/miri/src/shims/x86/avx.rs +++ b/src/tools/miri/src/shims/x86/avx.rs @@ -11,7 +11,6 @@ use super::{ FloatBinOp, FloatUnaryOp, }; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -23,7 +22,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "avx")?; // Prefix should have already been checked. @@ -343,8 +342,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.write_scalar(Scalar::from_i32(res.into()), dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/avx2.rs b/src/tools/miri/src/shims/x86/avx2.rs index bbf53f9f1e5..6e3468c0189 100644 --- a/src/tools/miri/src/shims/x86/avx2.rs +++ b/src/tools/miri/src/shims/x86/avx2.rs @@ -9,7 +9,6 @@ use super::{ packuswb, pmulhrsw, psign, shift_simd_by_scalar, shift_simd_by_simd, ShiftOp, }; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -21,7 +20,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "avx2")?; // Prefix should have already been checked. @@ -437,8 +436,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: shift_simd_by_simd(this, left, right, which, dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs index cf4d6a04bec..2ab2ae85905 100644 --- a/src/tools/miri/src/shims/x86/mod.rs +++ b/src/tools/miri/src/shims/x86/mod.rs @@ -10,7 +10,6 @@ use rustc_target::spec::abi::Abi; use crate::*; use helpers::bool_to_simd_element; -use shims::foreign_items::EmulateForeignItemResult; mod aesni; mod avx; @@ -31,7 +30,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.").unwrap(); @@ -43,7 +42,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: // https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/addcarry-u32-addcarry-u64.html "addcarry.32" | "addcarry.64" => { if unprefixed_name == "addcarry.64" && this.tcx.sess.target.arch != "x86_64" { - return Ok(EmulateForeignItemResult::NotSupported); + return Ok(EmulateItemResult::NotSupported); } let [c_in, a, b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?; @@ -69,7 +68,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: // https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/subborrow-u32-subborrow-u64.html "subborrow.32" | "subborrow.64" => { if unprefixed_name == "subborrow.64" && this.tcx.sess.target.arch != "x86_64" { - return Ok(EmulateForeignItemResult::NotSupported); + return Ok(EmulateItemResult::NotSupported); } let [b_in, a, b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?; @@ -143,9 +142,9 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: ); } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs index 17608837319..ea967a8cf72 100644 --- a/src/tools/miri/src/shims/x86/sse.rs +++ b/src/tools/miri/src/shims/x86/sse.rs @@ -8,7 +8,6 @@ use super::{ FloatUnaryOp, }; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -20,7 +19,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "sse")?; // Prefix should have already been checked. @@ -211,8 +210,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.copy_op(&this.project_index(&left, i)?, &this.project_index(&dest, i)?)?; } } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs index c9ed751d36c..31fa66a496f 100644 --- a/src/tools/miri/src/shims/x86/sse2.rs +++ b/src/tools/miri/src/shims/x86/sse2.rs @@ -7,7 +7,6 @@ use super::{ packuswb, shift_simd_by_scalar, FloatBinOp, ShiftOp, }; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -19,7 +18,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "sse2")?; // Prefix should have already been checked. @@ -387,8 +386,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.copy_op(&this.project_index(&left, i)?, &this.project_index(&dest, i)?)?; } } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/sse3.rs b/src/tools/miri/src/shims/x86/sse3.rs index 5ac30dca79a..8de339eb9e5 100644 --- a/src/tools/miri/src/shims/x86/sse3.rs +++ b/src/tools/miri/src/shims/x86/sse3.rs @@ -4,7 +4,6 @@ use rustc_target::spec::abi::Abi; use super::horizontal_bin_op; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -16,7 +15,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "sse3")?; // Prefix should have already been checked. @@ -50,8 +49,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.mem_copy(src_ptr, dest.ptr(), dest.layout.size, /*nonoverlapping*/ true)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/sse41.rs b/src/tools/miri/src/shims/x86/sse41.rs index 19bc27421d3..011a7a16c68 100644 --- a/src/tools/miri/src/shims/x86/sse41.rs +++ b/src/tools/miri/src/shims/x86/sse41.rs @@ -3,7 +3,6 @@ use rustc_target::spec::abi::Abi; use super::{conditional_dot_product, mpsadbw, packusdw, round_all, round_first, test_bits_masked}; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -15,7 +14,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "sse4.1")?; // Prefix should have already been checked. @@ -175,8 +174,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.write_scalar(Scalar::from_i32(res.into()), dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/ssse3.rs b/src/tools/miri/src/shims/x86/ssse3.rs index 4f8e52dbb7d..d30de430088 100644 --- a/src/tools/miri/src/shims/x86/ssse3.rs +++ b/src/tools/miri/src/shims/x86/ssse3.rs @@ -4,7 +4,6 @@ use rustc_target::spec::abi::Abi; use super::{horizontal_bin_op, int_abs, pmulhrsw, psign}; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -16,7 +15,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "ssse3")?; // Prefix should have already been checked. @@ -136,8 +135,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: psign(this, left, right, dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/tests/ui/check-cfg/cargo-feature.none.stderr b/tests/ui/check-cfg/cargo-feature.none.stderr index 09a1c950267..ae2351b82ce 100644 --- a/tests/ui/check-cfg/cargo-feature.none.stderr +++ b/tests/ui/check-cfg/cargo-feature.none.stderr @@ -6,7 +6,7 @@ LL | #[cfg(feature = "serde")] | = note: no expected values for `feature` = help: consider adding `serde` as a feature in `Cargo.toml` - = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration + = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: (none) @@ -17,7 +17,7 @@ LL | #[cfg(feature)] | = note: no expected values for `feature` = help: consider defining some features in `Cargo.toml` - = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration + = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `tokio_unstable` --> $DIR/cargo-feature.rs:22:7 @@ -26,8 +26,8 @@ LL | #[cfg(tokio_unstable)] | ^^^^^^^^^^^^^^ | = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` - = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(tokio_unstable)");` to the top of a `build.rs` - = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration + = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(tokio_unstable)");` to the top of the `build.rs` + = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `CONFIG_NVME` --> $DIR/cargo-feature.rs:26:7 @@ -35,8 +35,8 @@ warning: unexpected `cfg` condition name: `CONFIG_NVME` LL | #[cfg(CONFIG_NVME = "m")] | ^^^^^^^^^^^^^^^^^ | - = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(CONFIG_NVME, values(\"m\"))");` to the top of a `build.rs` - = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration + = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(CONFIG_NVME, values(\"m\"))");` to the top of the `build.rs` + = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration warning: 4 warnings emitted diff --git a/tests/ui/check-cfg/cargo-feature.some.stderr b/tests/ui/check-cfg/cargo-feature.some.stderr index 4db9c66fc86..191efbf2d54 100644 --- a/tests/ui/check-cfg/cargo-feature.some.stderr +++ b/tests/ui/check-cfg/cargo-feature.some.stderr @@ -6,7 +6,7 @@ LL | #[cfg(feature = "serde")] | = note: expected values for `feature` are: `bitcode` = help: consider adding `serde` as a feature in `Cargo.toml` - = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration + = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: (none) @@ -17,7 +17,7 @@ LL | #[cfg(feature)] | = note: expected values for `feature` are: `bitcode` = help: consider defining some features in `Cargo.toml` - = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration + = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `tokio_unstable` --> $DIR/cargo-feature.rs:22:7 @@ -26,8 +26,8 @@ LL | #[cfg(tokio_unstable)] | ^^^^^^^^^^^^^^ | = help: expected names are: `CONFIG_NVME`, `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` - = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(tokio_unstable)");` to the top of a `build.rs` - = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration + = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(tokio_unstable)");` to the top of the `build.rs` + = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `m` --> $DIR/cargo-feature.rs:26:7 @@ -38,8 +38,8 @@ LL | #[cfg(CONFIG_NVME = "m")] | help: there is a expected value with a similar name: `"y"` | = note: expected values for `CONFIG_NVME` are: `y` - = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(CONFIG_NVME, values(\"m\"))");` to the top of a `build.rs` - = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration + = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(CONFIG_NVME, values(\"m\"))");` to the top of the `build.rs` + = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration warning: 4 warnings emitted diff --git a/tests/ui/check-cfg/diagnotics.cargo.stderr b/tests/ui/check-cfg/diagnotics.cargo.stderr index 16417fe0105..1b7505682da 100644 --- a/tests/ui/check-cfg/diagnotics.cargo.stderr +++ b/tests/ui/check-cfg/diagnotics.cargo.stderr @@ -5,7 +5,7 @@ LL | #[cfg(featur)] | ^^^^^^ help: there is a config with a similar name: `feature` | = help: expected values for `feature` are: `foo` - = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration + = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `featur` @@ -14,7 +14,7 @@ warning: unexpected `cfg` condition name: `featur` LL | #[cfg(featur = "foo")] | ^^^^^^^^^^^^^^ | - = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration + = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration help: there is a config with a similar name and value | LL | #[cfg(feature = "foo")] @@ -27,7 +27,7 @@ LL | #[cfg(featur = "fo")] | ^^^^^^^^^^^^^ | = help: expected values for `feature` are: `foo` - = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration + = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration help: there is a config with a similar name and different values | LL | #[cfg(feature = "foo")] @@ -39,8 +39,8 @@ warning: unexpected `cfg` condition name: `no_value` LL | #[cfg(no_value)] | ^^^^^^^^ help: there is a config with a similar name: `no_values` | - = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(no_value)");` to the top of a `build.rs` - = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration + = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(no_value)");` to the top of the `build.rs` + = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `no_value` --> $DIR/diagnotics.rs:27:7 @@ -48,8 +48,8 @@ warning: unexpected `cfg` condition name: `no_value` LL | #[cfg(no_value = "foo")] | ^^^^^^^^^^^^^^^^ | - = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(no_value, values(\"foo\"))");` to the top of a `build.rs` - = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration + = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(no_value, values(\"foo\"))");` to the top of the `build.rs` + = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration help: there is a config with a similar name and no value | LL | #[cfg(no_values)] @@ -64,8 +64,8 @@ LL | #[cfg(no_values = "bar")] | help: remove the value | = note: no expected value for `no_values` - = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(no_values, values(\"bar\"))");` to the top of a `build.rs` - = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration + = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(no_values, values(\"bar\"))");` to the top of the `build.rs` + = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration warning: 6 warnings emitted diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr new file mode 100644 index 00000000000..a4d4b7b359e --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `*mut (): Foo` is not satisfied + --> $DIR/simple.rs:19:17 + | +LL | needs_foo::<*mut ()>(); + | ^^^^^^^ the trait `Send` is not implemented for `*mut ()`, which is required by `*mut (): Foo` + | +note: required for `*mut ()` to implement `Foo` + --> $DIR/simple.rs:10:9 + | +LL | impl<T> Foo for T where T: Send {} + | ^^^ ^ ---- unsatisfied trait bound introduced here +note: required by a bound in `needs_foo` + --> $DIR/simple.rs:14:17 + | +LL | fn needs_foo<T: Foo>() {} + | ^^^ required by this bound in `needs_foo` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr new file mode 100644 index 00000000000..1341ca8175a --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `*mut (): Foo` is not satisfied + --> $DIR/simple.rs:19:17 + | +LL | needs_foo::<*mut ()>(); + | ^^^^^^^ the trait `Foo` is not implemented for `*mut ()` + | +note: required by a bound in `needs_foo` + --> $DIR/simple.rs:14:17 + | +LL | fn needs_foo<T: Foo>() {} + | ^^^ required by this bound in `needs_foo` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs b/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs new file mode 100644 index 00000000000..15ff80ae4d9 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs @@ -0,0 +1,23 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +#![feature(do_not_recommend)] + +trait Foo {} + +#[do_not_recommend] +impl<T> Foo for T where T: Send {} +//[current]~^ NOTE required for `*mut ()` to implement `Foo` +//[current]~| NOTE unsatisfied trait bound introduced here + +fn needs_foo<T: Foo>() {} +//~^ NOTE required by a bound in `needs_foo` +//~| NOTE required by this bound in `needs_foo` + +fn main() { + needs_foo::<*mut ()>(); + //~^ ERROR the trait bound `*mut (): Foo` is not satisfied + //[current]~| NOTE the trait `Send` is not implemented for `*mut ()` + //[next]~| NOTE the trait `Foo` is not implemented for `*mut ()` +} diff --git a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs index bc9bb6ce2d7..8bb4ff46907 100644 --- a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs +++ b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs @@ -61,7 +61,7 @@ where // entering the cycle from `A` fails, but would work if we were to use the cache // result of `B<X>`. impls_trait::<A<X>, _, _, _>(); - //~^ ERROR the trait bound `X: IncompleteGuidance<_, _>` is not satisfied + //~^ ERROR the trait bound `A<X>: Trait<i32, u8, u8>` is not satisfied } fn main() { diff --git a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr index 78116ebba82..cdb4ff4588f 100644 --- a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr +++ b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr @@ -1,26 +1,28 @@ -error[E0277]: the trait bound `X: IncompleteGuidance<_, _>` is not satisfied +error[E0277]: the trait bound `A<X>: Trait<i32, u8, u8>` is not satisfied --> $DIR/incompleteness-unstable-result.rs:63:19 | LL | impls_trait::<A<X>, _, _, _>(); - | ^^^^ the trait `IncompleteGuidance<_, _>` is not implemented for `X`, which is required by `A<X>: Trait<_, _, _>` + | ^^^^ the trait `Trait<i32, u8, u8>` is not implemented for `A<X>`, which is required by `A<X>: Trait<_, _, _>` | - = help: the following other types implement trait `IncompleteGuidance<T, V>`: - <T as IncompleteGuidance<U, i16>> - <T as IncompleteGuidance<U, i8>> - <T as IncompleteGuidance<U, u8>> -note: required for `A<X>` to implement `Trait<_, _, u8>` +note: required for `A<X>` to implement `Trait<i32, u8, u8>` --> $DIR/incompleteness-unstable-result.rs:32:50 | LL | impl<T: ?Sized, U: ?Sized, V: ?Sized, D: ?Sized> Trait<U, V, D> for A<T> | ^^^^^^^^^^^^^^ ^^^^ -LL | where -LL | T: IncompleteGuidance<U, V>, - | ------------------------ unsatisfied trait bound introduced here +... +LL | A<T>: Trait<U, D, V>, + | -------------- unsatisfied trait bound introduced here + = note: 8 redundant requirements hidden + = note: required for `A<X>` to implement `Trait<i32, u8, u8>` note: required by a bound in `impls_trait` --> $DIR/incompleteness-unstable-result.rs:51:28 | LL | fn impls_trait<T: ?Sized + Trait<U, V, D>, U: ?Sized, V: ?Sized, D: ?Sized>() {} | ^^^^^^^^^^^^^^ required by this bound in `impls_trait` +help: consider extending the `where` clause, but there might be an alternative better way to express this requirement + | +LL | X: IncompleteGuidance<u32, i16>, A<X>: Trait<i32, u8, u8> + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to 1 previous error |
