diff --git a/Cargo.lock b/Cargo.lock index 1b89223c8bef1..c4704fb0dd593 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -444,7 +444,7 @@ dependencies = [ "directories", "rustc-build-sysroot", "rustc-workspace-hack", - "rustc_tools_util 0.2.1", + "rustc_tools_util", "rustc_version", "serde", "serde_json", @@ -738,7 +738,7 @@ dependencies = [ "regex", "rustc-semver", "rustc-workspace-hack", - "rustc_tools_util 0.3.0", + "rustc_tools_util", "semver", "serde", "syn", @@ -4725,12 +4725,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "rustc_tools_util" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598f48ce2a421542b3e64828aa742b687cc1b91d2f96591cfdb7ac5988cd6366" - [[package]] name = "rustc_tools_util" version = "0.3.0" diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index aa3a666b0b29c..39574ca558f8b 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1505,14 +1505,6 @@ pub struct PointeeInfo { pub safe: Option, } -/// Used in `might_permit_raw_init` to indicate the kind of initialisation -/// that is checked to be valid -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum InitKind { - Zero, - UninitMitigated0x01Fill, -} - impl LayoutS { /// Returns `true` if the layout corresponds to an unsized type. pub fn is_unsized(&self) -> bool { diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 6feb3a7732e12..f00e932107058 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -21,7 +21,8 @@ mod simd; pub(crate) use cpuid::codegen_cpuid_call; pub(crate) use llvm::codegen_llvm_intrinsic_call; -use rustc_middle::ty::layout::HasParamEnv; +use rustc_middle::ty; +use rustc_middle::ty::layout::{HasParamEnv, InitKind}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::subst::SubstsRef; use rustc_span::symbol::{kw, sym, Symbol}; @@ -642,7 +643,7 @@ fn codegen_regular_intrinsic_call<'tcx>( if intrinsic == sym::assert_zero_valid && !fx .tcx - .permits_zero_init(fx.param_env().and(ty)) + .check_validity_of_init((InitKind::Zero, fx.param_env().and(ty))) .expect("expected to have layout during codegen") { with_no_trimmed_paths!({ @@ -661,7 +662,10 @@ fn codegen_regular_intrinsic_call<'tcx>( if intrinsic == sym::assert_mem_uninitialized_valid && !fx .tcx - .permits_uninit_init(fx.param_env().and(ty)) + .check_validity_of_init(( + InitKind::UninitMitigated0x01Fill, + fx.param_env().and(ty), + )) .expect("expected to have layout during codegen") { with_no_trimmed_paths!({ diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index f6c1b7a98aae7..b1abbd673a53a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -14,7 +14,7 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::lang_items::LangItem; use rustc_index::vec::Idx; use rustc_middle::mir::{self, AssertKind, SwitchTargets}; -use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; +use rustc_middle::ty::layout::{HasTyCtxt, InitKind, LayoutOf}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Instance, Ty, TypeVisitableExt}; use rustc_session::config::OptLevel; @@ -676,11 +676,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { Inhabited => layout.abi.is_uninhabited(), ZeroValid => !bx .tcx() - .permits_zero_init(bx.param_env().and(ty)) + .check_validity_of_init((InitKind::Zero, bx.param_env().and(ty))) .expect("expected to have layout during codegen"), MemUninitializedValid => !bx .tcx() - .permits_uninit_init(bx.param_env().and(ty)) + .check_validity_of_init(( + InitKind::UninitMitigated0x01Fill, + bx.param_env().and(ty), + )) .expect("expected to have layout during codegen"), }; Some(if do_panic { diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 6e47646caeda8..26c84b4ce6127 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -11,7 +11,7 @@ use rustc_middle::mir::{ BinOp, NonDivergingIntrinsic, }; use rustc_middle::ty; -use rustc_middle::ty::layout::LayoutOf as _; +use rustc_middle::ty::layout::{InitKind, LayoutOf as _}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{Ty, TyCtxt}; use rustc_span::symbol::{sym, Symbol}; @@ -437,7 +437,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if intrinsic_name == sym::assert_zero_valid { let should_panic = !self .tcx - .permits_zero_init(self.param_env.and(ty)) + .check_validity_of_init((InitKind::Zero, self.param_env.and(ty))) .map_err(|_| err_inval!(TooGeneric))?; if should_panic { @@ -454,7 +454,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if intrinsic_name == sym::assert_mem_uninitialized_valid { let should_panic = !self .tcx - .permits_uninit_init(self.param_env.and(ty)) + .check_validity_of_init(( + InitKind::UninitMitigated0x01Fill, + self.param_env.and(ty), + )) .map_err(|_| err_inval!(TooGeneric))?; if should_panic { diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index fc6d61c79c2c4..092a7dc3d3b51 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -38,7 +38,6 @@ use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; use rustc_macros::fluent_messages; use rustc_middle::ty; use rustc_middle::ty::query::Providers; -use rustc_target::abi::InitKind; fluent_messages! { "../locales/en-US.ftl" } @@ -62,9 +61,7 @@ pub fn provide(providers: &mut Providers) { let (param_env, value) = param_env_and_value.into_parts(); const_eval::deref_mir_constant(tcx, param_env, value) }; - providers.permits_uninit_init = |tcx, param_env_and_ty| { - util::might_permit_raw_init(tcx, param_env_and_ty, InitKind::UninitMitigated0x01Fill) + providers.check_validity_of_init = |tcx, (init_kind, param_env_and_ty)| { + util::might_permit_raw_init(tcx, init_kind, param_env_and_ty) }; - providers.permits_zero_init = - |tcx, param_env_and_ty| util::might_permit_raw_init(tcx, param_env_and_ty, InitKind::Zero); } diff --git a/compiler/rustc_const_eval/src/util/might_permit_raw_init.rs b/compiler/rustc_const_eval/src/util/might_permit_raw_init.rs index 2eba1e11466a4..a78bf927ca1dc 100644 --- a/compiler/rustc_const_eval/src/util/might_permit_raw_init.rs +++ b/compiler/rustc_const_eval/src/util/might_permit_raw_init.rs @@ -1,7 +1,7 @@ -use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{InitKind, LayoutCx, LayoutError, LayoutOf, TyAndLayout}; use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Ty, TyCtxt}; use rustc_session::Limit; -use rustc_target::abi::{Abi, FieldsShape, InitKind, Scalar, Variants}; +use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants}; use crate::const_eval::{CheckAlignment, CompileTimeInterpreter}; use crate::interpret::{InterpCx, MemoryKind, OpTy}; @@ -20,8 +20,8 @@ use crate::interpret::{InterpCx, MemoryKind, OpTy}; /// to the full uninit check). pub fn might_permit_raw_init<'tcx>( tcx: TyCtxt<'tcx>, - param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>, kind: InitKind, + param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>, ) -> Result> { if tcx.sess.opts.unstable_opts.strict_init_checks { might_permit_raw_init_strict(tcx.layout_of(param_env_and_ty)?, tcx, kind) diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 89b4e6227bd61..b0dc6b1dcacc3 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -648,6 +648,13 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( tcx.fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs), ) .fold_with(&mut collector); + + debug_assert_ne!( + collector.types.len(), + 0, + "expect >1 RPITITs in call to `collect_return_position_impl_trait_in_trait_tys`" + ); + let trait_sig = ocx.normalize(&norm_cause, param_env, unnormalized_trait_sig); trait_sig.error_reported()?; let trait_return_ty = trait_sig.output(); diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 335eb4c54062f..a499018d3a2b0 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -438,7 +438,11 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } (VarValue::Value(a), VarValue::Empty(_)) => { match *a { - ReLateBound(..) | ReErased | ReError(_) => { + // this is always on an error path, + // so it doesn't really matter if it's shorter or longer than an empty region + ReError(_) => false, + + ReLateBound(..) | ReErased => { bug!("cannot relate region: {:?}", a); } @@ -467,7 +471,11 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } (VarValue::Empty(a_ui), VarValue::Value(b)) => { match *b { - ReLateBound(..) | ReErased | ReError(_) => { + // this is always on an error path, + // so it doesn't really matter if it's shorter or longer than an empty region + ReError(_) => false, + + ReLateBound(..) | ReErased => { bug!("cannot relate region: {:?}", b); } diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 2e2ca6a27888e..ad119c4e07306 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -64,13 +64,17 @@ impl ModuleItems { self.foreign_items.iter().copied() } - pub fn definitions(&self) -> impl Iterator + '_ { + pub fn owners(&self) -> impl Iterator + '_ { self.items .iter() - .map(|id| id.owner_id.def_id) - .chain(self.trait_items.iter().map(|id| id.owner_id.def_id)) - .chain(self.impl_items.iter().map(|id| id.owner_id.def_id)) - .chain(self.foreign_items.iter().map(|id| id.owner_id.def_id)) + .map(|id| id.owner_id) + .chain(self.trait_items.iter().map(|id| id.owner_id)) + .chain(self.impl_items.iter().map(|id| id.owner_id)) + .chain(self.foreign_items.iter().map(|id| id.owner_id)) + } + + pub fn definitions(&self) -> impl Iterator + '_ { + self.owners().map(|id| id.def_id) } pub fn par_items(&self, f: impl Fn(ItemId) + Send + Sync) { diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index dc02fd53ed02c..111ea6b8cddc0 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -4,8 +4,9 @@ use crate::infer::canonical::Canonical; use crate::mir; use crate::traits; use crate::ty::fast_reject::SimplifiedType; +use crate::ty::layout::{InitKind, TyAndLayout}; use crate::ty::subst::{GenericArg, SubstsRef}; -use crate::ty::{self, layout::TyAndLayout, Ty, TyCtxt}; +use crate::ty::{self, Ty, TyCtxt}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::hir_id::{HirId, OwnerId}; use rustc_query_system::query::{DefaultCacheSelector, SingleCacheSelector, VecCacheSelector}; @@ -696,3 +697,24 @@ impl Key for HirId { None } } + +impl<'tcx> Key for (InitKind, ty::ParamEnvAnd<'tcx, Ty<'tcx>>) { + type CacheSelector = DefaultCacheSelector; + + // Just forward to `Ty<'tcx>` + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true + } + + fn default_span(&self, _: TyCtxt<'_>) -> Span { + DUMMY_SP + } + + fn ty_adt_id(&self) -> Option { + match self.1.value.kind() { + ty::Adt(adt, _) => Some(adt.did()), + _ => None, + } + } +} diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 6a34e5ede1938..d4435a54b4ab6 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2173,12 +2173,8 @@ rustc_queries! { separate_provide_extern } - query permits_uninit_init(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> Result> { - desc { "checking to see if `{}` permits being left uninit", key.value } - } - - query permits_zero_init(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> Result> { - desc { "checking to see if `{}` permits being left zeroed", key.value } + query check_validity_of_init(key: (InitKind, ty::ParamEnvAnd<'tcx, Ty<'tcx>>)) -> Result> { + desc { "checking to see if `{}` permits being left {}", key.1.value, key.0 } } query compare_impl_const( diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 6c59cde86e39b..f0b52455889aa 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -169,6 +169,23 @@ pub const FAT_PTR_EXTRA: usize = 1; /// * Cranelift stores the base-2 log of the lane count in a 4 bit integer. pub const MAX_SIMD_LANES: u64 = 1 << 0xF; +/// Used in `might_permit_raw_init` to indicate the kind of initialisation +/// that is checked to be valid +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] +pub enum InitKind { + Zero, + UninitMitigated0x01Fill, +} + +impl fmt::Display for InitKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Zero => f.write_str("zeroed"), + Self::UninitMitigated0x01Fill => f.write_str("filled with 0x01"), + } + } +} + #[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)] pub enum LayoutError<'tcx> { Unknown(Ty<'tcx>), diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index 3d9a5075d4ade..d743c30684958 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -32,6 +32,7 @@ use crate::traits::specialization_graph; use crate::traits::{self, ImplSource}; use crate::ty::context::TyCtxtFeed; use crate::ty::fast_reject::SimplifiedType; +use crate::ty::layout::InitKind; use crate::ty::subst::{GenericArg, SubstsRef}; use crate::ty::util::AlwaysRequiresDrop; use crate::ty::GeneratorDiagnosticData; diff --git a/compiler/rustc_mir_transform/src/instcombine.rs b/compiler/rustc_mir_transform/src/instcombine.rs index 14e644bc344ca..05286b71d47e4 100644 --- a/compiler/rustc_mir_transform/src/instcombine.rs +++ b/compiler/rustc_mir_transform/src/instcombine.rs @@ -6,8 +6,8 @@ use rustc_middle::mir::{ BinOp, Body, Constant, ConstantKind, LocalDecls, Operand, Place, ProjectionElem, Rvalue, SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UnOp, }; -use rustc_middle::ty::layout::LayoutError; -use rustc_middle::ty::{self, ParamEnv, ParamEnvAnd, SubstsRef, Ty, TyCtxt}; +use rustc_middle::ty::layout::InitKind; +use rustc_middle::ty::{self, ParamEnv, SubstsRef, Ty, TyCtxt}; use rustc_span::symbol::{sym, Symbol}; pub struct InstCombine; @@ -234,16 +234,15 @@ impl<'tcx> InstCombineContext<'tcx, '_> { } let ty = substs.type_at(0); - // Check this is a foldable intrinsic before we query the layout of our generic parameter - let Some(assert_panics) = intrinsic_assert_panics(intrinsic_name) else { return; }; - match assert_panics(self.tcx, self.param_env.and(ty)) { - // We don't know the layout, don't touch the assertion - Err(_) => {} - Ok(true) => { + let known_is_valid = intrinsic_assert_panics(self.tcx, self.param_env, ty, intrinsic_name); + match known_is_valid { + // We don't know the layout or it's not validity assertion at all, don't touch it + None => {} + Some(true) => { // If we know the assert panics, indicate to later opts that the call diverges *target = None; } - Ok(false) => { + Some(false) => { // If we know the assert does not panic, turn the call into a Goto terminator.kind = TerminatorKind::Goto { target: *target_block }; } @@ -252,33 +251,21 @@ impl<'tcx> InstCombineContext<'tcx, '_> { } fn intrinsic_assert_panics<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, intrinsic_name: Symbol, -) -> Option, ParamEnvAnd<'tcx, Ty<'tcx>>) -> Result>> { - fn inhabited_predicate<'tcx>( - tcx: TyCtxt<'tcx>, - param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>, - ) -> Result> { - Ok(tcx.layout_of(param_env_and_ty)?.abi.is_uninhabited()) - } - fn zero_valid_predicate<'tcx>( - tcx: TyCtxt<'tcx>, - param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>, - ) -> Result> { - Ok(!tcx.permits_zero_init(param_env_and_ty)?) - } - fn mem_uninitialized_valid_predicate<'tcx>( - tcx: TyCtxt<'tcx>, - param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>, - ) -> Result> { - Ok(!tcx.permits_uninit_init(param_env_and_ty)?) - } - - match intrinsic_name { - sym::assert_inhabited => Some(inhabited_predicate), - sym::assert_zero_valid => Some(zero_valid_predicate), - sym::assert_mem_uninitialized_valid => Some(mem_uninitialized_valid_predicate), - _ => None, - } +) -> Option { + Some(match intrinsic_name { + sym::assert_inhabited => tcx.layout_of(param_env.and(ty)).ok()?.abi.is_uninhabited(), + sym::assert_zero_valid => { + !tcx.check_validity_of_init((InitKind::Zero, param_env.and(ty))).ok()? + } + sym::assert_mem_uninitialized_valid => !tcx + .check_validity_of_init((InitKind::UninitMitigated0x01Fill, param_env.and(ty))) + .ok()?, + _ => return None, + }) } fn resolve_rust_intrinsic<'tcx>( diff --git a/compiler/rustc_parse/locales/en-US.ftl b/compiler/rustc_parse/locales/en-US.ftl index a31b1f6ac1a0a..4ddeeed5b7e0a 100644 --- a/compiler/rustc_parse/locales/en-US.ftl +++ b/compiler/rustc_parse/locales/en-US.ftl @@ -220,7 +220,7 @@ parse_match_arm_body_without_braces = `match` arm body without braces [one] statement *[other] statements } with a body - .suggestion_use_comma_not_semicolon = use a comma to end a `match` arm expression + .suggestion_use_comma_not_semicolon = replace `;` with `,` to end a `match` arm expression parse_inclusive_range_extra_equals = unexpected `=` after inclusive range .suggestion_remove_eq = use `..=` instead diff --git a/compiler/rustc_passes/locales/en-US.ftl b/compiler/rustc_passes/locales/en-US.ftl index 0ed29ce0d4795..3fa78efc290ba 100644 --- a/compiler/rustc_passes/locales/en-US.ftl +++ b/compiler/rustc_passes/locales/en-US.ftl @@ -402,9 +402,6 @@ passes_invalid_attr_at_crate_level = `{$name}` attribute cannot be used at crate level .suggestion = perhaps you meant to use an outer attribute -passes_duplicate_diagnostic_item = - duplicate diagnostic item found: `{$name}`. - passes_duplicate_diagnostic_item_in_crate = duplicate diagnostic item in crate `{$crate_name}`: `{$name}`. .note = the diagnostic item is first defined in crate `{$orig_crate_name}`. diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index 0ae7096642cf1..110eb210df9ad 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -11,19 +11,19 @@ use rustc_ast as ast; use rustc_hir::diagnostic_items::DiagnosticItems; +use rustc_hir::OwnerId; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; -use rustc_span::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; -use rustc_span::symbol::{kw::Empty, sym, Symbol}; +use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use rustc_span::symbol::{sym, Symbol}; -use crate::errors::{DuplicateDiagnosticItem, DuplicateDiagnosticItemInCrate}; +use crate::errors::DuplicateDiagnosticItemInCrate; -fn observe_item(tcx: TyCtxt<'_>, diagnostic_items: &mut DiagnosticItems, def_id: LocalDefId) { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let attrs = tcx.hir().attrs(hir_id); +fn observe_item<'tcx>(tcx: TyCtxt<'tcx>, diagnostic_items: &mut DiagnosticItems, owner: OwnerId) { + let attrs = tcx.hir().attrs(owner.into()); if let Some(name) = extract(attrs) { // insert into our table - collect_item(tcx, diagnostic_items, name, def_id.to_def_id()); + collect_item(tcx, diagnostic_items, name, owner.to_def_id()); } } @@ -31,23 +31,29 @@ fn collect_item(tcx: TyCtxt<'_>, items: &mut DiagnosticItems, name: Symbol, item items.id_to_name.insert(item_def_id, name); if let Some(original_def_id) = items.name_to_id.insert(name, item_def_id) { if original_def_id != item_def_id { - let orig_span = tcx.hir().span_if_local(original_def_id); - let orig_crate_name = - orig_span.is_none().then(|| tcx.crate_name(original_def_id.krate)); - match tcx.hir().span_if_local(item_def_id) { - Some(span) => tcx.sess.emit_err(DuplicateDiagnosticItem { span, name }), - None => tcx.sess.emit_err(DuplicateDiagnosticItemInCrate { - span: orig_span, - orig_crate_name: orig_crate_name.unwrap_or(Empty), - have_orig_crate_name: orig_crate_name.map(|_| ()), - crate_name: tcx.crate_name(item_def_id.krate), - name, - }), - }; + report_duplicate_item(tcx, name, original_def_id, item_def_id); } } } +fn report_duplicate_item( + tcx: TyCtxt<'_>, + name: Symbol, + original_def_id: DefId, + item_def_id: DefId, +) { + let orig_span = tcx.hir().span_if_local(original_def_id); + let duplicate_span = tcx.hir().span_if_local(item_def_id); + tcx.sess.emit_err(DuplicateDiagnosticItemInCrate { + duplicate_span, + orig_span, + crate_name: tcx.crate_name(item_def_id.krate), + orig_crate_name: tcx.crate_name(original_def_id.krate), + different_crates: (item_def_id.krate != original_def_id.krate).then_some(()), + name, + }); +} + /// Extract the first `rustc_diagnostic_item = "$name"` out of a list of attributes. fn extract(attrs: &[ast::Attribute]) -> Option { attrs.iter().find_map(|attr| { @@ -64,21 +70,8 @@ fn diagnostic_items(tcx: TyCtxt<'_>, cnum: CrateNum) -> DiagnosticItems { // Collect diagnostic items in this crate. let crate_items = tcx.hir_crate_items(()); - - for id in crate_items.items() { - observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id); - } - - for id in crate_items.trait_items() { - observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id); - } - - for id in crate_items.impl_items() { - observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id); - } - - for id in crate_items.foreign_items() { - observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id); + for id in crate_items.owners() { + observe_item(tcx, &mut diagnostic_items, id); } diagnostic_items diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 2c0d21b479848..9f1c0b5a0b7bd 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -809,23 +809,17 @@ impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel { } } -#[derive(Diagnostic)] -#[diag(passes_duplicate_diagnostic_item)] -pub struct DuplicateDiagnosticItem { - #[primary_span] - pub span: Span, - pub name: Symbol, -} - #[derive(Diagnostic)] #[diag(passes_duplicate_diagnostic_item_in_crate)] pub struct DuplicateDiagnosticItemInCrate { + #[primary_span] + pub duplicate_span: Option, #[note(passes_diagnostic_item_first_defined)] - pub span: Option, - pub orig_crate_name: Symbol, + pub orig_span: Option, #[note] - pub have_orig_crate_name: Option<()>, + pub different_crates: Option<()>, pub crate_name: Symbol, + pub orig_crate_name: Symbol, pub name: Symbol, } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index e5b0f9d3300a6..d542240be9b24 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1307,21 +1307,38 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>( let _ = selcx.infcx.commit_if_ok(|_| { match selcx.select(&obligation.with(tcx, trait_predicate)) { Ok(Some(super::ImplSource::UserDefined(data))) => { - candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data)); - Ok(()) + let Ok(leaf_def) = specialization_graph::assoc_def(tcx, data.impl_def_id, trait_fn_def_id) else { + return Err(()); + }; + // Only reveal a specializable default if we're past type-checking + // and the obligation is monomorphic, otherwise passes such as + // transmute checking and polymorphic MIR optimizations could + // get a result which isn't correct for all monomorphizations. + if leaf_def.is_final() + || (obligation.param_env.reveal() == Reveal::All + && !selcx + .infcx + .resolve_vars_if_possible(obligation.predicate.trait_ref(tcx)) + .still_further_specializable()) + { + candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data)); + Ok(()) + } else { + Err(()) + } } Ok(None) => { candidate_set.mark_ambiguous(); - return Err(()); + Err(()) } Ok(Some(_)) => { // Don't know enough about the impl to provide a useful signature - return Err(()); + Err(()) } Err(e) => { debug!(error = ?e, "selection error"); candidate_set.mark_error(e); - return Err(()); + Err(()) } } }); diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index ff7821fb9ff08..cd19667139ab6 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -105,10 +105,15 @@ impl Step for Std { cargo.arg("--lib"); } - builder.info(&format!( - "Checking stage{} library artifacts ({} -> {})", - builder.top_stage, &compiler.host, target - )); + let msg = if compiler.host == target { + format!("Checking stage{} library artifacts ({target})", builder.top_stage) + } else { + format!( + "Checking stage{} library artifacts ({} -> {})", + builder.top_stage, &compiler.host, target + ) + }; + builder.info(&msg); run_cargo( builder, cargo, @@ -162,10 +167,18 @@ impl Step for Std { cargo.arg("-p").arg(krate.name); } - builder.info(&format!( - "Checking stage{} library test/bench/example targets ({} -> {})", - builder.top_stage, &compiler.host, target - )); + let msg = if compiler.host == target { + format!( + "Checking stage{} library test/bench/example targets ({target})", + builder.top_stage + ) + } else { + format!( + "Checking stage{} library test/bench/example targets ({} -> {})", + builder.top_stage, &compiler.host, target + ) + }; + builder.info(&msg); run_cargo( builder, cargo, @@ -239,10 +252,15 @@ impl Step for Rustc { cargo.arg("-p").arg(krate.name); } - builder.info(&format!( - "Checking stage{} compiler artifacts ({} -> {})", - builder.top_stage, &compiler.host, target - )); + let msg = if compiler.host == target { + format!("Checking stage{} compiler artifacts ({target})", builder.top_stage) + } else { + format!( + "Checking stage{} compiler artifacts ({} -> {})", + builder.top_stage, &compiler.host, target + ) + }; + builder.info(&msg); run_cargo( builder, cargo, @@ -299,10 +317,15 @@ impl Step for CodegenBackend { .arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend))); rustc_cargo_env(builder, &mut cargo, target); - builder.info(&format!( - "Checking stage{} {} artifacts ({} -> {})", - builder.top_stage, backend, &compiler.host.triple, target.triple - )); + let msg = if compiler.host == target { + format!("Checking stage{} {} artifacts ({target})", builder.top_stage, backend) + } else { + format!( + "Checking stage{} {} library ({} -> {})", + builder.top_stage, backend, &compiler.host.triple, target.triple + ) + }; + builder.info(&msg); run_cargo( builder, @@ -362,10 +385,15 @@ impl Step for RustAnalyzer { cargo.arg("--benches"); } - builder.info(&format!( - "Checking stage{} {} artifacts ({} -> {})", - compiler.stage, "rust-analyzer", &compiler.host.triple, target.triple - )); + let msg = if compiler.host == target { + format!("Checking stage{} {} artifacts ({target})", compiler.stage, "rust-analyzer") + } else { + format!( + "Checking stage{} {} artifacts ({} -> {})", + compiler.stage, "rust-analyzer", &compiler.host.triple, target.triple + ) + }; + builder.info(&msg); run_cargo( builder, cargo, @@ -432,14 +460,18 @@ macro_rules! tool_check_step { // NOTE: this doesn't enable lints for any other tools unless they explicitly add `#![warn(rustc::internal)]` // See https://github.com/rust-lang/rust/pull/80573#issuecomment-754010776 cargo.rustflag("-Zunstable-options"); - - builder.info(&format!( - "Checking stage{} {} artifacts ({} -> {})", - builder.top_stage, - stringify!($name).to_lowercase(), - &compiler.host.triple, - target.triple - )); + let msg = if compiler.host == target { + format!("Checking stage{} {} artifacts ({target})", builder.top_stage, stringify!($name).to_lowercase()) + } else { + format!( + "Checking stage{} {} artifacts ({} -> {})", + builder.top_stage, + stringify!($name).to_lowercase(), + &compiler.host.triple, + target.triple + ) + }; + builder.info(&msg); run_cargo( builder, cargo, diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 1e6c94d29ba47..b3fc889431b38 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -463,11 +463,10 @@ function initSearch(rawSearchIndex) { * @param {ParserState} parserState */ function parseInput(query, parserState) { - let c, before; let foundStopChar = true; while (parserState.pos < parserState.length) { - c = parserState.userQuery[parserState.pos]; + const c = parserState.userQuery[parserState.pos]; if (isStopCharacter(c)) { foundStopChar = true; if (isSeparatorCharacter(c)) { @@ -506,7 +505,7 @@ function initSearch(rawSearchIndex) { } throw new Error(`Expected \`,\`, \` \`, \`:\` or \`->\`, found \`${c}\``); } - before = query.elems.length; + const before = query.elems.length; getNextElem(query, parserState, query.elems, false); if (query.elems.length === before) { // Nothing was added, weird... Let's increase the position to not remain stuck. @@ -515,7 +514,6 @@ function initSearch(rawSearchIndex) { foundStopChar = false; } while (parserState.pos < parserState.length) { - c = parserState.userQuery[parserState.pos]; if (isReturnArrow(parserState)) { parserState.pos += 2; // Get returned elements. @@ -1940,7 +1938,6 @@ function initSearch(rawSearchIndex) { */ const searchWords = []; const charA = "A".charCodeAt(0); - let i, word; let currentIndex = 0; let id = 0; @@ -2035,7 +2032,7 @@ function initSearch(rawSearchIndex) { // convert `rawPaths` entries into object form // generate normalizedPaths for function search mode let len = paths.length; - for (i = 0; i < len; ++i) { + for (let i = 0; i < len; ++i) { lowercasePaths.push({ty: paths[i][0], name: paths[i][1].toLowerCase()}); paths[i] = {ty: paths[i][0], name: paths[i][1]}; } @@ -2049,16 +2046,14 @@ function initSearch(rawSearchIndex) { // faster analysis operations len = itemTypes.length; let lastPath = ""; - for (i = 0; i < len; ++i) { + for (let i = 0; i < len; ++i) { + let word = ""; // This object should have exactly the same set of fields as the "crateRow" // object defined above. if (typeof itemNames[i] === "string") { word = itemNames[i].toLowerCase(); - searchWords.push(word); - } else { - word = ""; - searchWords.push(""); } + searchWords.push(word); const row = { crate: crate, ty: itemTypes.charCodeAt(i) - charA, diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js index 0e1c864e62d84..6c0f03b5bb072 100644 --- a/src/librustdoc/html/static/js/source-script.js +++ b/src/librustdoc/html/static/js/source-script.js @@ -117,8 +117,7 @@ function createSourceSidebar() { sidebar.appendChild(title); Object.keys(sourcesIndex).forEach(key => { sourcesIndex[key][NAME_OFFSET] = key; - hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "", - hasFoundFile); + hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "", hasFoundFile); }); container.appendChild(sidebar); diff --git a/src/tools/miri/CONTRIBUTING.md b/src/tools/miri/CONTRIBUTING.md index 5b538691de183..476075e9c914d 100644 --- a/src/tools/miri/CONTRIBUTING.md +++ b/src/tools/miri/CONTRIBUTING.md @@ -242,6 +242,13 @@ josh-proxy --local=$HOME/.cache/josh --remote=https://github.com --no-background This uses a directory `$HOME/.cache/josh` as a cache, to speed up repeated pulling/pushing. +To make josh push via ssh instead of https, you can add the following to your `.gitconfig`: + +```toml +[url "git@github.com:"] + pushInsteadOf = https://github.com/ +``` + ### Importing changes from the rustc repo Josh needs to be running, as described above. diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index 48581f6bbff1a..1086d0481c835 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -213,7 +213,9 @@ degree documented below): - The best-supported target is `x86_64-unknown-linux-gnu`. Miri releases are blocked on things working with this target. Most other Linux targets should also work well; we do run the test suite on `i686-unknown-linux-gnu` as a - 32bit target and `mips64-unknown-linux-gnuabi64` as a big-endian target. + 32bit target and `mips64-unknown-linux-gnuabi64` as a big-endian target, as + well as the ARM targets `aarch64-unknown-linux-gnu` and + `arm-unknown-linux-gnueabi`. - `x86_64-apple-darwin` should work basically as well as Linux. We also test `aarch64-apple-darwin`. However, we might ship Miri with a nightly even when some features on these targets regress. @@ -590,7 +592,7 @@ extern "Rust" { /// `out` must point to at least `out_size` many bytes, and the result will be stored there /// with a null terminator. /// Returns 0 if the `out` buffer was large enough, and the required size otherwise. - fn miri_host_to_target_path(path: *const i8, out: *mut i8, out_size: usize) -> usize; + fn miri_host_to_target_path(path: *const std::ffi::c_char, out: *mut std::ffi::c_char, out_size: usize) -> usize; } ``` diff --git a/src/tools/miri/cargo-miri/Cargo.lock b/src/tools/miri/cargo-miri/Cargo.lock index 37926db0166b7..76badcf94afb3 100644 --- a/src/tools/miri/cargo-miri/Cargo.lock +++ b/src/tools/miri/cargo-miri/Cargo.lock @@ -193,9 +193,9 @@ checksum = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb" [[package]] name = "rustc_tools_util" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598f48ce2a421542b3e64828aa742b687cc1b91d2f96591cfdb7ac5988cd6366" +checksum = "8ba09476327c4b70ccefb6180f046ef588c26a24cf5d269a9feba316eb4f029f" [[package]] name = "rustc_version" diff --git a/src/tools/miri/cargo-miri/Cargo.toml b/src/tools/miri/cargo-miri/Cargo.toml index 2197160bc9d44..09079dbb818be 100644 --- a/src/tools/miri/cargo-miri/Cargo.toml +++ b/src/tools/miri/cargo-miri/Cargo.toml @@ -30,4 +30,4 @@ rustc-workspace-hack = "1.0.0" serde = { version = "*", features = ["derive"] } [build-dependencies] -rustc_tools_util = "0.2" +rustc_tools_util = "0.3" diff --git a/src/tools/miri/cargo-miri/build.rs b/src/tools/miri/cargo-miri/build.rs index c111011545590..52e2a083512c4 100644 --- a/src/tools/miri/cargo-miri/build.rs +++ b/src/tools/miri/cargo-miri/build.rs @@ -2,12 +2,5 @@ fn main() { // Don't rebuild miri when nothing changed. println!("cargo:rerun-if-changed=build.rs"); // gather version info - println!( - "cargo:rustc-env=GIT_HASH={}", - rustc_tools_util::get_commit_hash().unwrap_or_default() - ); - println!( - "cargo:rustc-env=COMMIT_DATE={}", - rustc_tools_util::get_commit_date().unwrap_or_default() - ); + rustc_tools_util::setup_version_info!(); } diff --git a/src/tools/miri/ci.sh b/src/tools/miri/ci.sh index e01bfbc74d98a..60450d0981545 100755 --- a/src/tools/miri/ci.sh +++ b/src/tools/miri/ci.sh @@ -104,6 +104,7 @@ run_tests case $HOST_TARGET in x86_64-unknown-linux-gnu) MIRI_TEST_TARGET=i686-unknown-linux-gnu run_tests + MIRI_TEST_TARGET=aarch64-unknown-linux-gnu run_tests MIRI_TEST_TARGET=aarch64-apple-darwin run_tests MIRI_TEST_TARGET=i686-pc-windows-msvc run_tests MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple atomic data_race env/var @@ -118,6 +119,7 @@ case $HOST_TARGET in MIRI_TEST_TARGET=x86_64-pc-windows-msvc run_tests ;; i686-pc-windows-msvc) + MIRI_TEST_TARGET=arm-unknown-linux-gnueabi run_tests MIRI_TEST_TARGET=x86_64-unknown-linux-gnu run_tests MIRI_TEST_TARGET=x86_64-pc-windows-gnu run_tests ;; diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index cf6d9c2808048..53ec1ba0821b0 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -c54c8cbac882e149e04a9e1f2d146fd548ae30ae +c4e0cd966062ca67daed20775f4e8a60c28e57df diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index cf1ff603281ee..b766916402e4f 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -148,8 +148,7 @@ impl NewPermission { NewPermission::Uniform { perm: Permission::Unique, access: Some(AccessKind::Write), - protector: (kind == RetagKind::FnEntry) - .then_some(ProtectorKind::WeakProtector), + protector: (kind == RetagKind::FnEntry).then_some(ProtectorKind::WeakProtector), } } else { // `!Unpin` boxes do not get `noalias` nor `dereferenceable`. diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 7024927b20561..f64f216520f00 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -13,6 +13,7 @@ #![allow( clippy::collapsible_else_if, clippy::collapsible_if, + clippy::if_same_then_else, clippy::comparison_chain, clippy::enum_variant_names, clippy::field_reassign_with_default, @@ -21,7 +22,7 @@ clippy::single_match, clippy::useless_format, clippy::derive_partial_eq_without_eq, - clippy::derive_hash_xor_eq, + clippy::derived_hash_with_manual_eq, clippy::too_many_arguments, clippy::type_complexity, clippy::single_element_loop, diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 8bd1e802f8a52..8bbf9f87b43e5 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -477,7 +477,8 @@ pub struct MiriMachine<'mir, 'tcx> { impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { pub(crate) fn new(config: &MiriConfig, layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>) -> Self { - let local_crates = helpers::get_local_crates(layout_cx.tcx); + let tcx = layout_cx.tcx; + let local_crates = helpers::get_local_crates(tcx); let layouts = PrimitiveLayouts::new(layout_cx).expect("Couldn't get layouts of primitive types"); let profiler = config.measureme_out.as_ref().map(|out| { @@ -486,10 +487,13 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { let rng = StdRng::seed_from_u64(config.seed.unwrap_or(0)); let borrow_tracker = config.borrow_tracker.map(|bt| bt.instanciate_global_state(config)); let data_race = config.data_race_detector.then(|| data_race::GlobalState::new(config)); + // Determinine page size, stack address, and stack size. + // These values are mostly meaningless, but the stack address is also where we start + // allocating physical integer addresses for all allocations. let page_size = if let Some(page_size) = config.page_size { page_size } else { - let target = &layout_cx.tcx.sess.target; + let target = &tcx.sess.target; match target.arch.as_ref() { "wasm32" | "wasm64" => 64 * 1024, // https://webassembly.github.io/spec/core/exec/runtime.html#memory-instances "aarch64" => @@ -504,10 +508,12 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { _ => 4 * 1024, } }; - let stack_addr = page_size * 32; - let stack_size = page_size * 16; + // On 16bit targets, 32 pages is more than the entire address space! + let stack_addr = if tcx.pointer_size().bits() < 32 { page_size } else { page_size * 32 }; + let stack_size = + if tcx.pointer_size().bits() < 32 { page_size * 4 } else { page_size * 16 }; MiriMachine { - tcx: layout_cx.tcx, + tcx, borrow_tracker, data_race, intptrcast: RefCell::new(intptrcast::GlobalStateInner::new(config, stack_addr)), @@ -902,8 +908,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { }; let (shim_size, shim_align, _kind) = ecx.get_alloc_info(alloc_id); let def_ty = ecx.tcx.type_of(def_id).subst_identity(); - let extern_decl_layout = - ecx.tcx.layout_of(ty::ParamEnv::empty().and(def_ty)).unwrap(); + let extern_decl_layout = ecx.tcx.layout_of(ty::ParamEnv::empty().and(def_ty)).unwrap(); if extern_decl_layout.size != shim_size || extern_decl_layout.align.abi != shim_align { throw_unsup_format!( "`extern` static `{name}` from crate `{krate}` has been declared \ diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 2d9eb37a25806..03275ed4ed163 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -885,6 +885,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } } + "llvm.arm.hint" if this.tcx.sess.target.arch == "arm" => { + let [arg] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?; + let arg = this.read_scalar(arg)?.to_i32()?; + match arg { + // YIELD + 1 => { + this.yield_active_thread(); + } + _ => { + throw_unsup_format!("unsupported llvm.arm.hint argument {}", arg); + } + } + } // Platform-specific shims _ => diff --git a/src/tools/miri/src/shims/unix/linux/fd.rs b/src/tools/miri/src/shims/unix/linux/fd.rs index 212b7936341a7..fd4927fa10ce3 100644 --- a/src/tools/miri/src/shims/unix/linux/fd.rs +++ b/src/tools/miri/src/shims/unix/linux/fd.rs @@ -7,6 +7,8 @@ use socketpair::SocketPair; use shims::unix::fs::EvalContextExt as _; +use std::cell::Cell; + pub mod epoll; pub mod event; pub mod socketpair; @@ -101,6 +103,60 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } + /// The `epoll_wait()` system call waits for events on the `Epoll` + /// instance referred to by the file descriptor `epfd`. The buffer + /// pointed to by `events` is used to return information from the ready + /// list about file descriptors in the interest list that have some + /// events available. Up to `maxevents` are returned by `epoll_wait()`. + /// The `maxevents` argument must be greater than zero. + + /// The `timeout` argument specifies the number of milliseconds that + /// `epoll_wait()` will block. Time is measured against the + /// CLOCK_MONOTONIC clock. + + /// A call to `epoll_wait()` will block until either: + /// • a file descriptor delivers an event; + /// • the call is interrupted by a signal handler; or + /// • the timeout expires. + + /// Note that the timeout interval will be rounded up to the system + /// clock granularity, and kernel scheduling delays mean that the + /// blocking interval may overrun by a small amount. Specifying a + /// timeout of -1 causes `epoll_wait()` to block indefinitely, while + /// specifying a timeout equal to zero cause `epoll_wait()` to return + /// immediately, even if no events are available. + /// + /// On success, `epoll_wait()` returns the number of file descriptors + /// ready for the requested I/O, or zero if no file descriptor became + /// ready during the requested timeout milliseconds. On failure, + /// `epoll_wait()` returns -1 and errno is set to indicate the error. + /// + /// + fn epoll_wait( + &mut self, + epfd: &OpTy<'tcx, Provenance>, + events: &OpTy<'tcx, Provenance>, + maxevents: &OpTy<'tcx, Provenance>, + timeout: &OpTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + + let epfd = this.read_scalar(epfd)?.to_i32()?; + let _events = this.read_scalar(events)?.to_pointer(this)?; + let _maxevents = this.read_scalar(maxevents)?.to_i32()?; + let _timeout = this.read_scalar(timeout)?.to_i32()?; + + let numevents = 0; + if let Some(epfd) = this.machine.file_handler.handles.get_mut(&epfd) { + let _epfd = epfd.as_epoll_handle()?; + + // FIXME return number of events ready when scheme for marking events ready exists + Ok(Scalar::from_i32(numevents)) + } else { + Ok(Scalar::from_i32(this.handle_not_found()?)) + } + } + /// This function creates an `Event` that is used as an event wait/notify mechanism by /// user-space applications, and by the kernel to notify user-space applications of events. /// The `Event` contains an `u64` counter maintained by the kernel. The counter is initialized @@ -142,7 +198,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } let fh = &mut this.machine.file_handler; - let fd = fh.insert_fd(Box::new(Event { val })); + let fd = fh.insert_fd(Box::new(Event { val: Cell::new(val.into()) })); Ok(Scalar::from_i32(fd)) } diff --git a/src/tools/miri/src/shims/unix/linux/fd/event.rs b/src/tools/miri/src/shims/unix/linux/fd/event.rs index 239eb462a1d23..b28a6e0c56eca 100644 --- a/src/tools/miri/src/shims/unix/linux/fd/event.rs +++ b/src/tools/miri/src/shims/unix/linux/fd/event.rs @@ -2,6 +2,7 @@ use crate::shims::unix::fs::FileDescriptor; use rustc_const_eval::interpret::InterpResult; +use std::cell::Cell; use std::io; /// A kind of file descriptor created by `eventfd`. @@ -13,7 +14,9 @@ use std::io; /// #[derive(Debug)] pub struct Event { - pub val: u32, + /// The object contains an unsigned 64-bit integer (uint64_t) counter that is maintained by the + /// kernel. This counter is initialized with the value specified in the argument initval. + pub val: Cell, } impl FileDescriptor for Event { @@ -22,7 +25,7 @@ impl FileDescriptor for Event { } fn dup(&mut self) -> io::Result> { - Ok(Box::new(Event { val: self.val })) + Ok(Box::new(Event { val: self.val.clone() })) } fn is_tty(&self) -> bool { @@ -35,4 +38,32 @@ impl FileDescriptor for Event { ) -> InterpResult<'tcx, io::Result> { Ok(Ok(0)) } + + /// A write call adds the 8-byte integer value supplied in + /// its buffer to the counter. The maximum value that may be + /// stored in the counter is the largest unsigned 64-bit value + /// minus 1 (i.e., 0xfffffffffffffffe). If the addition would + /// cause the counter's value to exceed the maximum, then the + /// write either blocks until a read is performed on the + /// file descriptor, or fails with the error EAGAIN if the + /// file descriptor has been made nonblocking. + + /// A write fails with the error EINVAL if the size of the + /// supplied buffer is less than 8 bytes, or if an attempt is + /// made to write the value 0xffffffffffffffff. + /// + /// FIXME: use endianness + fn write<'tcx>( + &self, + _communicate_allowed: bool, + bytes: &[u8], + ) -> InterpResult<'tcx, io::Result> { + let v1 = self.val.get(); + // FIXME handle blocking when addition results in exceeding the max u64 value + // or fail with EAGAIN if the file descriptor is nonblocking. + let v2 = v1.checked_add(u64::from_be_bytes(bytes.try_into().unwrap())).unwrap(); + self.val.set(v2); + assert_eq!(8, bytes.len()); + Ok(Ok(8)) + } } 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 9f6938424fb2d..f4e7824d91df4 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -55,6 +55,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let result = this.epoll_ctl(epfd, op, fd, event)?; this.write_scalar(result, dest)?; } + "epoll_wait" => { + let [epfd, events, maxevents, timeout] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let result = this.epoll_wait(epfd, events, maxevents, timeout)?; + this.write_scalar(result, dest)?; + } "eventfd" => { let [val, flag] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; diff --git a/src/tools/miri/test-cargo-miri/src/main.rs b/src/tools/miri/test-cargo-miri/src/main.rs index 048dbbbaa0f06..048577ef15a61 100644 --- a/src/tools/miri/test-cargo-miri/src/main.rs +++ b/src/tools/miri/test-cargo-miri/src/main.rs @@ -23,7 +23,7 @@ fn main() { // (We rely on the test runner to always disable isolation when passing no arguments.) if std::env::args().len() <= 1 { fn host_to_target_path(path: String) -> PathBuf { - use std::ffi::{CStr, CString}; + use std::ffi::{c_char, CStr, CString}; let path = CString::new(path).unwrap(); let mut out = Vec::with_capacity(1024); @@ -31,8 +31,8 @@ fn main() { unsafe { extern "Rust" { fn miri_host_to_target_path( - path: *const i8, - out: *mut i8, + path: *const c_char, + out: *mut c_char, out_size: usize, ) -> usize; } diff --git a/src/tools/miri/test-cargo-miri/subcrate/main.rs b/src/tools/miri/test-cargo-miri/subcrate/main.rs index 1cb8091f87750..52161098788b5 100644 --- a/src/tools/miri/test-cargo-miri/subcrate/main.rs +++ b/src/tools/miri/test-cargo-miri/subcrate/main.rs @@ -5,7 +5,7 @@ fn main() { println!("subcrate running"); fn host_to_target_path(path: String) -> PathBuf { - use std::ffi::{CStr, CString}; + use std::ffi::{c_char, CStr, CString}; let path = CString::new(path).unwrap(); let mut out = Vec::with_capacity(1024); @@ -13,8 +13,8 @@ fn main() { unsafe { extern "Rust" { fn miri_host_to_target_path( - path: *const i8, - out: *mut i8, + path: *const c_char, + out: *mut c_char, out_size: usize, ) -> usize; } diff --git a/src/tools/miri/test-cargo-miri/subcrate/test.rs b/src/tools/miri/test-cargo-miri/subcrate/test.rs index 619d8c72fd0a7..1681c721dc2e2 100644 --- a/src/tools/miri/test-cargo-miri/subcrate/test.rs +++ b/src/tools/miri/test-cargo-miri/subcrate/test.rs @@ -8,7 +8,7 @@ fn main() { println!("subcrate testing"); fn host_to_target_path(path: String) -> PathBuf { - use std::ffi::{CStr, CString}; + use std::ffi::{c_char, CStr, CString}; let path = CString::new(path).unwrap(); let mut out = Vec::with_capacity(1024); @@ -16,8 +16,8 @@ fn main() { unsafe { extern "Rust" { fn miri_host_to_target_path( - path: *const i8, - out: *mut i8, + path: *const c_char, + out: *mut c_char, out_size: usize, ) -> usize; } diff --git a/src/tools/miri/test_dependencies/Cargo.lock b/src/tools/miri/test_dependencies/Cargo.lock index a84ed85976367..8be1ee54672d8 100644 --- a/src/tools/miri/test_dependencies/Cargo.lock +++ b/src/tools/miri/test_dependencies/Cargo.lock @@ -292,9 +292,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.23.1" +version = "1.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38a54aca0c15d014013256222ba0ebed095673f89345dd79119d912eb561b7a8" +checksum = "597a12a59981d9e3c38d216785b0c37399f6e415e8d0712047620f189371b0bb" dependencies = [ "autocfg", "bytes", diff --git a/src/tools/miri/test_dependencies/Cargo.toml b/src/tools/miri/test_dependencies/Cargo.toml index f5ab6acf008c5..d1ff33379e40a 100644 --- a/src/tools/miri/test_dependencies/Cargo.toml +++ b/src/tools/miri/test_dependencies/Cargo.toml @@ -18,6 +18,6 @@ rand = { version = "0.8", features = ["small_rng"] } [target.'cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))'.dependencies] page_size = "0.5" -tokio = { version = "1.23", features = ["full"] } +tokio = { version = "1.24", features = ["full"] } [workspace] diff --git a/src/tools/miri/tests/fail/unaligned_pointers/reference_to_packed.rs b/src/tools/miri/tests/fail/unaligned_pointers/reference_to_packed.rs index 816b6ab9fb32f..4a43db0aac50a 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/reference_to_packed.rs +++ b/src/tools/miri/tests/fail/unaligned_pointers/reference_to_packed.rs @@ -3,7 +3,7 @@ #![allow(dead_code, unused_variables)] -use std::{ptr, mem}; +use std::{mem, ptr}; #[repr(packed)] struct Foo { diff --git a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs index ba5b269f65242..cd071a7f32ac1 100644 --- a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs @@ -5,7 +5,7 @@ #![feature(io_error_uncategorized)] use std::convert::TryInto; -use std::ffi::{CStr, CString}; +use std::ffi::{c_char, CStr, CString}; use std::fs::{canonicalize, remove_dir_all, remove_file, File}; use std::io::{Error, ErrorKind, Write}; use std::os::unix::ffi::OsStrExt; @@ -31,7 +31,11 @@ fn tmp() -> PathBuf { unsafe { extern "Rust" { - fn miri_host_to_target_path(path: *const i8, out: *mut i8, out_size: usize) -> usize; + fn miri_host_to_target_path( + path: *const c_char, + out: *mut c_char, + out_size: usize, + ) -> usize; } let ret = miri_host_to_target_path(path.as_ptr(), out.as_mut_ptr(), out.capacity()); assert_eq!(ret, 0); diff --git a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs index 20e96a92c7c5f..98e1c3a0adb2e 100644 --- a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs +++ b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs @@ -7,7 +7,7 @@ use std::os::unix::io::AsRawFd; use std::path::PathBuf; fn tmp() -> PathBuf { - use std::ffi::{CStr, CString}; + use std::ffi::{c_char, CStr, CString}; let path = std::env::var("MIRI_TEMP") .unwrap_or_else(|_| std::env::temp_dir().into_os_string().into_string().unwrap()); @@ -17,7 +17,11 @@ fn tmp() -> PathBuf { unsafe { extern "Rust" { - fn miri_host_to_target_path(path: *const i8, out: *mut i8, out_size: usize) -> usize; + fn miri_host_to_target_path( + path: *const c_char, + out: *mut c_char, + out_size: usize, + ) -> usize; } let ret = miri_host_to_target_path(path.as_ptr(), out.as_mut_ptr(), out.capacity()); assert_eq!(ret, 0); diff --git a/src/tools/miri/tests/pass-dep/tokio/sleep.rs b/src/tools/miri/tests/pass-dep/tokio/sleep.rs new file mode 100644 index 0000000000000..1341484dda475 --- /dev/null +++ b/src/tools/miri/tests/pass-dep/tokio/sleep.rs @@ -0,0 +1,14 @@ +//@compile-flags: -Zmiri-disable-isolation -Zmiri-permissive-provenance -Zmiri-backtrace=full +//@only-target-x86_64-unknown-linux: support for tokio only on linux and x86 + +use tokio::time::{sleep, Duration, Instant}; + +#[tokio::main] +async fn main() { + let start = Instant::now(); + sleep(Duration::from_secs(1)).await; + // It takes 96 millisecond to sleep for 1 millisecond + // It takes 1025 millisecond to sleep for 1 second + let time_elapsed = &start.elapsed().as_millis(); + assert!(time_elapsed > &1000, "{}", time_elapsed); +} diff --git a/src/tools/miri/tests/pass-dep/tokio_mvp.rs b/src/tools/miri/tests/pass-dep/tokio/tokio_mvp.rs similarity index 88% rename from src/tools/miri/tests/pass-dep/tokio_mvp.rs rename to src/tools/miri/tests/pass-dep/tokio/tokio_mvp.rs index 642168253c2fa..0bca7cc069a78 100644 --- a/src/tools/miri/tests/pass-dep/tokio_mvp.rs +++ b/src/tools/miri/tests/pass-dep/tokio/tokio_mvp.rs @@ -1,5 +1,5 @@ // Need to disable preemption to stay on the supported MVP codepath in mio. -//@compile-flags: -Zmiri-disable-isolation -Zmiri-permissive-provenance -Zmiri-preemption-rate=0 +//@compile-flags: -Zmiri-disable-isolation -Zmiri-permissive-provenance //@only-target-x86_64-unknown-linux: support for tokio exists only on linux and x86 #[tokio::main] diff --git a/src/tools/miri/tests/pass/dyn-star.rs b/src/tools/miri/tests/pass/dyn-star.rs index 16a8cec6cdae1..1fac16352a448 100644 --- a/src/tools/miri/tests/pass/dyn-star.rs +++ b/src/tools/miri/tests/pass/dyn-star.rs @@ -1,5 +1,8 @@ #![feature(dyn_star)] #![allow(incomplete_features)] +#![feature(custom_inner_attributes)] +// rustfmt destroys `dyn* Trait` syntax +#![rustfmt::skip] use std::fmt::{Debug, Display}; diff --git a/src/tools/miri/tests/pass/move-data-across-await-point.rs b/src/tools/miri/tests/pass/move-data-across-await-point.rs new file mode 100644 index 0000000000000..489fae66ffb2b --- /dev/null +++ b/src/tools/miri/tests/pass/move-data-across-await-point.rs @@ -0,0 +1,81 @@ +use std::future::Future; +use std::ptr; + +// This test: +// - Compares addresses of non-Copy data before and after moving it +// - Writes to the pointer after it has moved across the await point +// +// This is only meant to assert current behavior, not guarantee that this is +// how it should work in the future. In fact, upcoming changes to rustc +// *should* break these tests. +// See: https://github.com/rust-lang/rust/issues/62958 +async fn data_moved_async() { + async fn helper(mut data: Vec, raw_pointer: *mut Vec) { + let raw_pointer2 = ptr::addr_of_mut!(data); + // `raw_pointer` points to the original location where the Vec was stored in the caller. + // `data` is where that Vec (to be precise, its ptr+capacity+len on-stack data) + // got moved to. Those will usually not be the same since the Vec got moved twice + // (into the function call, and then into the generator upvar). + assert_ne!(raw_pointer, raw_pointer2); + unsafe { + // This writes into the `x` in `data_moved_async`, re-initializing it. + std::ptr::write(raw_pointer, vec![3]); + } + } + // Vec is not Copy + let mut x: Vec = vec![2]; + let raw_pointer = ptr::addr_of_mut!(x); + helper(x, raw_pointer).await; + unsafe { + assert_eq!(*raw_pointer, vec![3]); + // Drop to prevent leak. + std::ptr::drop_in_place(raw_pointer); + } +} + +// Same thing as above, but non-async. +fn data_moved() { + fn helper(mut data: Vec, raw_pointer: *mut Vec) { + let raw_pointer2 = ptr::addr_of_mut!(data); + assert_ne!(raw_pointer, raw_pointer2); + unsafe { + std::ptr::write(raw_pointer, vec![3]); + } + } + + let mut x: Vec = vec![2]; + let raw_pointer = ptr::addr_of_mut!(x); + helper(x, raw_pointer); + unsafe { + assert_eq!(*raw_pointer, vec![3]); + std::ptr::drop_in_place(raw_pointer); + } +} + +fn run_fut(fut: impl Future) -> T { + use std::sync::Arc; + use std::task::{Context, Poll, Wake, Waker}; + + struct MyWaker; + impl Wake for MyWaker { + fn wake(self: Arc) { + unimplemented!() + } + } + + let waker = Waker::from(Arc::new(MyWaker)); + let mut context = Context::from_waker(&waker); + + let mut pinned = Box::pin(fut); + loop { + match pinned.as_mut().poll(&mut context) { + Poll::Pending => continue, + Poll::Ready(v) => return v, + } + } +} + +fn main() { + run_fut(data_moved_async()); + data_moved(); +} diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs index a7d4800faecc4..7a9974f393895 100644 --- a/src/tools/miri/tests/pass/shims/fs.rs +++ b/src/tools/miri/tests/pass/shims/fs.rs @@ -6,7 +6,7 @@ #![feature(is_terminal)] use std::collections::HashMap; -use std::ffi::OsString; +use std::ffi::{c_char, OsString}; use std::fs::{ canonicalize, create_dir, read_dir, read_link, remove_dir, remove_dir_all, remove_file, rename, File, OpenOptions, @@ -39,7 +39,11 @@ fn host_to_target_path(path: String) -> PathBuf { unsafe { extern "Rust" { - fn miri_host_to_target_path(path: *const i8, out: *mut i8, out_size: usize) -> usize; + fn miri_host_to_target_path( + path: *const c_char, + out: *mut c_char, + out_size: usize, + ) -> usize; } let ret = miri_host_to_target_path(path.as_ptr(), out.as_mut_ptr(), out.capacity()); assert_eq!(ret, 0); diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs new file mode 100644 index 0000000000000..afd3db5e0525e --- /dev/null +++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs @@ -0,0 +1,71 @@ +// edition: 2021 +// known-bug: #108309 + +#![feature(async_fn_in_trait)] +#![feature(min_specialization)] + +struct MyStruct; + +trait MyTrait { + async fn foo(_: T) -> &'static str; +} + +impl MyTrait for MyStruct { + default async fn foo(_: T) -> &'static str { + "default" + } +} + +impl MyTrait for MyStruct { + async fn foo(_: i32) -> &'static str { + "specialized" + } +} + +async fn async_main() { + assert_eq!(MyStruct::foo(42).await, "specialized"); + assert_eq!(indirection(42).await, "specialized"); +} + +async fn indirection(x: T) -> &'static str { + //explicit type coercion is currently necessary + // because of https://github.com/rust-lang/rust/issues/67918 + >::foo(x).await +} + +// ------------------------------------------------------------------------- // +// Implementation Details Below... + +use std::future::Future; +use std::pin::Pin; +use std::task::*; + +pub fn noop_waker() -> Waker { + let raw = RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE); + + // SAFETY: the contracts for RawWaker and RawWakerVTable are upheld + unsafe { Waker::from_raw(raw) } +} + +const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop); + +unsafe fn noop_clone(_p: *const ()) -> RawWaker { + RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE) +} + +unsafe fn noop(_p: *const ()) {} + +fn main() { + let mut fut = async_main(); + + // Poll loop, just to test the future... + let waker = noop_waker(); + let ctx = &mut Context::from_waker(&waker); + + loop { + match unsafe { Pin::new_unchecked(&mut fut).poll(ctx) } { + Poll::Pending => {} + Poll::Ready(()) => break, + } + } +} diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr new file mode 100644 index 0000000000000..371122ea71ec0 --- /dev/null +++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr @@ -0,0 +1,26 @@ +warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/dont-project-to-specializable-projection.rs:4:12 + | +LL | #![feature(async_fn_in_trait)] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #91611 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0053]: method `foo` has an incompatible type for trait + --> $DIR/dont-project-to-specializable-projection.rs:14:35 + | +LL | default async fn foo(_: T) -> &'static str { + | ^^^^^^^^^^^^ expected associated type, found future + | +note: type in trait + --> $DIR/dont-project-to-specializable-projection.rs:10:27 + | +LL | async fn foo(_: T) -> &'static str; + | ^^^^^^^^^^^^ + = note: expected signature `fn(_) -> impl Future` + found signature `fn(_) -> impl Future` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/lifetimes/issue-107988.rs b/tests/ui/lifetimes/issue-107988.rs new file mode 100644 index 0000000000000..92cb60a06a2b0 --- /dev/null +++ b/tests/ui/lifetimes/issue-107988.rs @@ -0,0 +1,13 @@ +pub trait TraitEngine<'tcx>: 'tcx {} + +pub trait TraitEngineExt<'tcx> { + fn register_predicate_obligations(&mut self); +} + +impl> TraitEngineExt<'tcx> for T { + //~^ ERROR use of undeclared lifetime name `'tcx` + //~| ERROR use of undeclared lifetime name `'tcx` + fn register_predicate_obligations(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/lifetimes/issue-107988.stderr b/tests/ui/lifetimes/issue-107988.stderr new file mode 100644 index 0000000000000..c2d8c7050e97f --- /dev/null +++ b/tests/ui/lifetimes/issue-107988.stderr @@ -0,0 +1,27 @@ +error[E0261]: use of undeclared lifetime name `'tcx` + --> $DIR/issue-107988.rs:7:52 + | +LL | impl> TraitEngineExt<'tcx> for T { + | - ^^^^ undeclared lifetime + | | + | help: consider introducing lifetime `'tcx` here: `'tcx,` + +error[E0261]: use of undeclared lifetime name `'tcx` + --> $DIR/issue-107988.rs:7:30 + | +LL | impl> TraitEngineExt<'tcx> for T { + | ^^^^ undeclared lifetime + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'tcx` lifetime + | +LL | impl TraitEngine<'tcx>> TraitEngineExt<'tcx> for T { + | +++++++++ +help: consider introducing lifetime `'tcx` here + | +LL | impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T { + | +++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/parser/match-arm-without-braces.stderr b/tests/ui/parser/match-arm-without-braces.stderr index 37d55aa53f87c..ee1c8e562fc33 100644 --- a/tests/ui/parser/match-arm-without-braces.stderr +++ b/tests/ui/parser/match-arm-without-braces.stderr @@ -2,10 +2,14 @@ error: `match` arm body without braces --> $DIR/match-arm-without-braces.rs:26:27 | LL | Some(Val::Foo) => 3; - | -- ^- help: use a comma to end a `match` arm expression: `,` - | | | - | | this statement is not surrounded by a body + | -- ^ this statement is not surrounded by a body + | | | while parsing the `match` arm starting here + | +help: replace `;` with `,` to end a `match` arm expression + | +LL | Some(Val::Foo) => 3, + | ~ error: `match` arm body without braces --> $DIR/match-arm-without-braces.rs:31:11 diff --git a/tests/ui/tool-attributes/duplicate-diagnostic.rs b/tests/ui/tool-attributes/duplicate-diagnostic.rs index 39c2ca1cb860c..e2cf9508757be 100644 --- a/tests/ui/tool-attributes/duplicate-diagnostic.rs +++ b/tests/ui/tool-attributes/duplicate-diagnostic.rs @@ -9,5 +9,5 @@ extern crate p1; extern crate p2; #[rustc_diagnostic_item = "Foo"] -pub struct Foo {} //~ ERROR duplicate diagnostic item found +pub struct Foo {} //~ ERROR duplicate diagnostic item in crate `duplicate_diagnostic`: `Foo` fn main() {} diff --git a/tests/ui/tool-attributes/duplicate-diagnostic.stderr b/tests/ui/tool-attributes/duplicate-diagnostic.stderr index e315fdc7d84bc..26bd6a82e3417 100644 --- a/tests/ui/tool-attributes/duplicate-diagnostic.stderr +++ b/tests/ui/tool-attributes/duplicate-diagnostic.stderr @@ -2,11 +2,13 @@ error: duplicate diagnostic item in crate `p2`: `Foo`. | = note: the diagnostic item is first defined in crate `p1`. -error: duplicate diagnostic item found: `Foo`. +error: duplicate diagnostic item in crate `duplicate_diagnostic`: `Foo`. --> $DIR/duplicate-diagnostic.rs:12:1 | LL | pub struct Foo {} | ^^^^^^^^^^^^^^ + | + = note: the diagnostic item is first defined in crate `p2`. error: aborting due to 2 previous errors diff --git a/triagebot.toml b/triagebot.toml index 7a26457ab04c0..f7607d522c1b9 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -482,7 +482,6 @@ compiler-team = [ "@davidtwco", "@oli-obk", "@lcnr", - "@nagisa", "@wesleywiser", "@michaelwoerister", ] @@ -552,7 +551,6 @@ mir = [ "@oli-obk", ] mir-opt = [ - "@nagisa", "@oli-obk", "@wesleywiser", ]