diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 854974d1605a5..0fcbaa2efabb8 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -198,7 +198,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { | sym::assert_zero_valid | sym::assert_mem_uninitialized_valid => (1, Vec::new(), tcx.mk_unit()), sym::forget => (1, vec![param(0)], tcx.mk_unit()), - sym::transmute => (2, vec![param(0)], param(1)), + sym::transmute | sym::transmute_unchecked => (2, vec![param(0)], param(1)), sym::prefetch_read_data | sym::prefetch_write_data | sym::prefetch_read_instruction diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 6747da7abd3af..e61037e5ea86f 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -139,40 +139,6 @@ impl<'tcx> TyCtxt<'tcx> { treat_projections: TreatProjections, mut f: impl FnMut(DefId), ) { - let _: Option<()> = - self.find_map_relevant_impl(trait_def_id, self_ty, treat_projections, |did| { - f(did); - None - }); - } - - /// `trait_def_id` MUST BE the `DefId` of a trait. - pub fn non_blanket_impls_for_ty( - self, - trait_def_id: DefId, - self_ty: Ty<'tcx>, - ) -> impl Iterator + 'tcx { - let impls = self.trait_impls_of(trait_def_id); - if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsCandidateKey) { - if let Some(impls) = impls.non_blanket_impls.get(&simp) { - return impls.iter().copied(); - } - } - - [].iter().copied() - } - - /// Applies function to every impl that could possibly match the self type `self_ty` and returns - /// the first non-none value. - /// - /// `trait_def_id` MUST BE the `DefId` of a trait. - pub fn find_map_relevant_impl( - self, - trait_def_id: DefId, - self_ty: Ty<'tcx>, - treat_projections: TreatProjections, - mut f: impl FnMut(DefId) -> Option, - ) -> Option { // FIXME: This depends on the set of all impls for the trait. That is // unfortunate wrt. incremental compilation. // @@ -181,9 +147,7 @@ impl<'tcx> TyCtxt<'tcx> { let impls = self.trait_impls_of(trait_def_id); for &impl_def_id in impls.blanket_impls.iter() { - if let result @ Some(_) = f(impl_def_id) { - return result; - } + f(impl_def_id); } // Note that we're using `TreatParams::ForLookup` to query `non_blanket_impls` while using @@ -199,20 +163,30 @@ impl<'tcx> TyCtxt<'tcx> { if let Some(simp) = fast_reject::simplify_type(self, self_ty, treat_params) { if let Some(impls) = impls.non_blanket_impls.get(&simp) { for &impl_def_id in impls { - if let result @ Some(_) = f(impl_def_id) { - return result; - } + f(impl_def_id); } } } else { for &impl_def_id in impls.non_blanket_impls.values().flatten() { - if let result @ Some(_) = f(impl_def_id) { - return result; - } + f(impl_def_id); } } + } - None + /// `trait_def_id` MUST BE the `DefId` of a trait. + pub fn non_blanket_impls_for_ty( + self, + trait_def_id: DefId, + self_ty: Ty<'tcx>, + ) -> impl Iterator + 'tcx { + let impls = self.trait_impls_of(trait_def_id); + if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsCandidateKey) { + if let Some(impls) = impls.non_blanket_impls.get(&simp) { + return impls.iter().copied(); + } + } + + [].iter().copied() } /// Returns an iterator containing all impls for `trait_def_id`. diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index dbe2eebe33604..9dbd9fbbb5bb3 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -2,7 +2,6 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::mir; -use crate::ty::fast_reject::TreatProjections; use crate::ty::layout::IntegerExt; use crate::ty::{ self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, @@ -359,21 +358,29 @@ impl<'tcx> TyCtxt<'tcx> { self.ensure().coherent_trait(drop_trait); let ty = self.type_of(adt_did).subst_identity(); - let (did, constness) = self.find_map_relevant_impl( - drop_trait, - ty, - // FIXME: This could also be some other mode, like "unexpected" - TreatProjections::ForLookup, - |impl_did| { - if let Some(item_id) = self.associated_item_def_ids(impl_did).first() { - if validate(self, impl_did).is_ok() { - return Some((*item_id, self.constness(impl_did))); - } - } - None - }, - )?; + let mut dtor_candidate = None; + self.for_each_relevant_impl(drop_trait, ty, |impl_did| { + let Some(item_id) = self.associated_item_def_ids(impl_did).first() else { + self.sess.delay_span_bug(self.def_span(impl_did), "Drop impl without drop function"); + return; + }; + + if validate(self, impl_did).is_err() { + // Already `ErrorGuaranteed`, no need to delay a span bug here. + return; + } + + if let Some((old_item_id, _)) = dtor_candidate { + self.sess + .struct_span_err(self.def_span(item_id), "multiple drop impls found") + .span_note(self.def_span(old_item_id), "other impl here") + .delay_as_bug(); + } + + dtor_candidate = Some((*item_id, self.constness(impl_did))); + }); + let (did, constness) = dtor_candidate?; Some(ty::Destructor { did, constness }) } diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index a56c5cc5c12f9..c0861f99620d1 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -323,7 +323,7 @@ impl<'tcx> std::fmt::Debug for ScalarTy<'tcx> { impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: Map) -> Self { - let param_env = tcx.param_env(body.source.def_id()); + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); Self { map, tcx, diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index 9447a2ff04095..430a6f6cef5be 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -120,7 +120,7 @@ impl EnumSizeOpt { fn optim<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let mut alloc_cache = FxHashMap::default(); let body_did = body.source.def_id(); - let param_env = tcx.param_env(body_did); + let param_env = tcx.param_env_reveal_all_normalized(body_did); let blocks = body.basic_blocks.as_mut(); let local_decls = &mut body.local_decls; diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index c136642dff277..c7d3f6c9f044c 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -221,7 +221,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { terminator.kind = TerminatorKind::Goto { target }; } } - sym::transmute => { + sym::transmute | sym::transmute_unchecked => { let dst_ty = destination.ty(local_decls, tcx).ty; let Ok([arg]) = <[_; 1]>::try_from(std::mem::take(args)) else { span_bug!( diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index ce05db5b762ac..59942dc76f9aa 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -46,7 +46,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let def_id = body.source.def_id(); - let param_env = tcx.param_env(def_id); + let param_env = tcx.param_env_reveal_all_normalized(def_id); let bbs = body.basic_blocks.as_mut(); let mut should_cleanup = false; diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs index abe6cb285f505..23442f8b97b7e 100644 --- a/compiler/rustc_mir_transform/src/reveal_all.rs +++ b/compiler/rustc_mir_transform/src/reveal_all.rs @@ -34,11 +34,23 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> { self.tcx } + #[inline] + fn visit_constant(&mut self, constant: &mut Constant<'tcx>, _: Location) { + // We have to use `try_normalize_erasing_regions` here, since it's + // possible that we visit impossible-to-satisfy where clauses here, + // see #91745 + if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.param_env, constant.literal) { + constant.literal = c; + } + } + #[inline] fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) { // We have to use `try_normalize_erasing_regions` here, since it's // possible that we visit impossible-to-satisfy where clauses here, // see #91745 - *ty = self.tcx.try_normalize_erasing_regions(self.param_env, *ty).unwrap_or(*ty); + if let Ok(t) = self.tcx.try_normalize_erasing_regions(self.param_env, *ty) { + *ty = t; + } } } diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 4396a83e8b818..d4debae5c581a 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -355,7 +355,7 @@ fn build_thread_local_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'t fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> { debug!("build_clone_shim(def_id={:?})", def_id); - let param_env = tcx.param_env(def_id); + let param_env = tcx.param_env_reveal_all_normalized(def_id); let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty); let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env); @@ -836,7 +836,7 @@ fn build_call_shim<'tcx>( pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { debug_assert!(tcx.is_constructor(ctor_id)); - let param_env = tcx.param_env(ctor_id); + let param_env = tcx.param_env_reveal_all_normalized(ctor_id); // Normalize the sig. let sig = tcx diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs index c65a7ec6783fa..1ff488169864b 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -16,7 +16,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyConstCondition { } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let param_env = tcx.param_env(body.source.def_id()); + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); for block in body.basic_blocks_mut() { let terminator = block.terminator_mut(); terminator.kind = match terminator.kind { diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs index dcad1518eb63e..113ca2fc5ada5 100644 --- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs +++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs @@ -37,7 +37,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyComparisonIntegral { let opts = helper.find_optimizations(); let mut storage_deads_to_insert = vec![]; let mut storage_deads_to_remove: Vec<(usize, BasicBlock)> = vec![]; - let param_env = tcx.param_env(body.source.def_id()); + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); for opt in opts { trace!("SUCCESS: Applying {:?}", opt); // replace terminator with a switchInt that switches on the integer directly diff --git a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs index be0aa0fc4c1d0..5389b9f52eb2d 100644 --- a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs @@ -109,7 +109,9 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { continue; }; - let layout = tcx.layout_of(tcx.param_env(body.source.def_id()).and(discriminant_ty)); + let layout = tcx.layout_of( + tcx.param_env_reveal_all_normalized(body.source.def_id()).and(discriminant_ty), + ); let allowed_variants = if let Ok(layout) = layout { variant_discriminants(&layout, discriminant_ty, tcx) diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 01f002c940840..192badcbc37ea 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -223,3 +223,6 @@ resolve_remove_surrounding_derive = resolve_add_as_non_derive = add as non-Derive macro `#[{$macro_path}]` + +resolve_proc_macro_same_crate = can't use a procedural macro from the same crate that defines it + .help = you can define integration tests in a directory named `tests` diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index af0ec236df063..6197af105a965 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -508,3 +508,12 @@ pub(crate) struct RemoveSurroundingDerive { pub(crate) struct AddAsNonDerive<'a> { pub(crate) macro_path: &'a str, } + +#[derive(Diagnostic)] +#[diag(resolve_proc_macro_same_crate)] +pub(crate) struct ProcMacroSameCrate { + #[primary_span] + pub(crate) span: Span, + #[help] + pub(crate) is_test: bool, +} diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 22b014c0651c2..2211fb56ccda1 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -1,7 +1,7 @@ //! A bunch of methods and structures more or less related to resolving macros and //! interface provided by `Resolver` to macro expander. -use crate::errors::{AddAsNonDerive, MacroExpectedFound, RemoveSurroundingDerive}; +use crate::errors::{self, AddAsNonDerive, MacroExpectedFound, RemoveSurroundingDerive}; use crate::Namespace::*; use crate::{BuiltinMacroState, Determinacy}; use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet}; @@ -513,10 +513,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(def_id) = def_id.as_local() { self.unused_macros.remove(&def_id); if self.proc_macro_stubs.contains(&def_id) { - self.tcx.sess.span_err( - path.span, - "can't use a procedural macro from the same crate that defines it", - ); + self.tcx.sess.emit_err(errors::ProcMacroSameCrate { + span: path.span, + is_test: self.tcx.sess.is_test_crate(), + }); } } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 9891915d076dd..70b9088de5064 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1505,6 +1505,7 @@ symbols! { transmute_generic_consts, transmute_opts, transmute_trait, + transmute_unchecked, transparent, transparent_enums, transparent_unions, diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 1abcc80d01a32..8e7097ce4a779 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -645,12 +645,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // FIXME: Handling opaques here is kinda sus. Especially because we // simplify them to PlaceholderSimplifiedType. | ty::Alias(ty::Opaque, _) => { - if let Some(def_id) = self.tcx().find_map_relevant_impl( + let mut disqualifying_impl = None; + self.tcx().for_each_relevant_impl_treating_projections( goal.predicate.def_id(), goal.predicate.self_ty(), TreatProjections::NextSolverLookup, - Some, - ) { + |impl_def_id| { + disqualifying_impl = Some(impl_def_id); + }, + ); + if let Some(def_id) = disqualifying_impl { debug!(?def_id, ?goal, "disqualified auto-trait implementation"); // No need to actually consider the candidate here, // since we do that in `consider_impl_candidate`. diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index ae21dcd2a360c..61e382bbe49d6 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -32,7 +32,6 @@ use rustc_infer::infer::{InferOk, TypeTrace}; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::fast_reject::TreatProjections; use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print}; use rustc_middle::ty::{ @@ -1836,57 +1835,61 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { }); let mut diag = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271, "{msg}"); - let secondary_span = match predicate.kind().skip_binder() { - ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => self - .tcx - .opt_associated_item(proj.projection_ty.def_id) - .and_then(|trait_assoc_item| { - self.tcx - .trait_of_item(proj.projection_ty.def_id) - .map(|id| (trait_assoc_item, id)) - }) - .and_then(|(trait_assoc_item, id)| { - let trait_assoc_ident = trait_assoc_item.ident(self.tcx); - self.tcx.find_map_relevant_impl( - id, - proj.projection_ty.self_ty(), - TreatProjections::ForLookup, - |did| { - self.tcx - .associated_items(did) - .in_definition_order() - .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident) - }, - ) - }) - .and_then(|item| match self.tcx.hir().get_if_local(item.def_id) { - Some( - hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Type(_, Some(ty)), - .. - }) - | hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Type(ty), - .. - }), - ) => Some(( - ty.span, - with_forced_trimmed_paths!(format!( - "type mismatch resolving `{}`", - self.resolve_vars_if_possible(predicate) - .print(FmtPrinter::new_with_limit( - self.tcx, - Namespace::TypeNS, - rustc_session::Limit(5), - )) - .unwrap() - .into_buffer() - )), + let secondary_span = (|| { + let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = + predicate.kind().skip_binder() + else { + return None; + }; + + let trait_assoc_item = self.tcx.opt_associated_item(proj.projection_ty.def_id)?; + let trait_assoc_ident = trait_assoc_item.ident(self.tcx); + + let mut associated_items = vec![]; + self.tcx.for_each_relevant_impl( + self.tcx.trait_of_item(proj.projection_ty.def_id)?, + proj.projection_ty.self_ty(), + |impl_def_id| { + associated_items.extend( + self.tcx + .associated_items(impl_def_id) + .in_definition_order() + .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident), + ); + }, + ); + + let [associated_item]: &[ty::AssocItem] = &associated_items[..] else { + return None; + }; + match self.tcx.hir().get_if_local(associated_item.def_id) { + Some( + hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Type(_, Some(ty)), + .. + }) + | hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Type(ty), + .. + }), + ) => Some(( + ty.span, + with_forced_trimmed_paths!(format!( + "type mismatch resolving `{}`", + self.resolve_vars_if_possible(predicate) + .print(FmtPrinter::new_with_limit( + self.tcx, + Namespace::TypeNS, + rustc_session::Limit(5), + )) + .unwrap() + .into_buffer() )), - _ => None, - }), - _ => None, - }; + )), + _ => None, + } + })(); + self.note_type_err( &mut diag, &obligation.cause, @@ -2228,14 +2231,18 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { err: &mut Diagnostic, trait_ref: &ty::PolyTraitRef<'tcx>, ) -> bool { - let get_trait_impl = |trait_def_id| { - self.tcx.find_map_relevant_impl( + let get_trait_impls = |trait_def_id| { + let mut trait_impls = vec![]; + self.tcx.for_each_relevant_impl( trait_def_id, trait_ref.skip_binder().self_ty(), - TreatProjections::ForLookup, - Some, - ) + |impl_def_id| { + trait_impls.push(impl_def_id); + }, + ); + trait_impls }; + let required_trait_path = self.tcx.def_path_str(trait_ref.def_id()); let traits_with_same_path: std::collections::BTreeSet<_> = self .tcx @@ -2245,17 +2252,23 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { .collect(); let mut suggested = false; for trait_with_same_path in traits_with_same_path { - if let Some(impl_def_id) = get_trait_impl(trait_with_same_path) { - let impl_span = self.tcx.def_span(impl_def_id); - err.span_help(impl_span, "trait impl with same name found"); - let trait_crate = self.tcx.crate_name(trait_with_same_path.krate); - let crate_msg = format!( - "perhaps two different versions of crate `{}` are being used?", - trait_crate - ); - err.note(&crate_msg); - suggested = true; + let trait_impls = get_trait_impls(trait_with_same_path); + if trait_impls.is_empty() { + continue; } + let impl_spans: Vec<_> = + trait_impls.iter().map(|impl_def_id| self.tcx.def_span(*impl_def_id)).collect(); + err.span_help( + impl_spans, + format!("trait impl{} with same name found", pluralize!(trait_impls.len())), + ); + let trait_crate = self.tcx.crate_name(trait_with_same_path.krate); + let crate_msg = format!( + "perhaps two different versions of crate `{}` are being used?", + trait_crate + ); + err.note(&crate_msg); + suggested = true; } suggested } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 6ba0538717348..ea45412e47f11 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1272,14 +1272,29 @@ fn project<'cx, 'tcx>( ProjectionCandidateSet::Single(candidate) => { Ok(Projected::Progress(confirm_candidate(selcx, obligation, candidate))) } - ProjectionCandidateSet::None => Ok(Projected::NoProgress( - // FIXME(associated_const_generics): this may need to change in the future? - // need to investigate whether or not this is fine. - selcx - .tcx() - .mk_projection(obligation.predicate.def_id, obligation.predicate.substs) - .into(), - )), + ProjectionCandidateSet::None => { + let tcx = selcx.tcx(); + let term = match tcx.def_kind(obligation.predicate.def_id) { + DefKind::AssocTy | DefKind::ImplTraitPlaceholder => tcx + .mk_projection(obligation.predicate.def_id, obligation.predicate.substs) + .into(), + DefKind::AssocConst => tcx + .mk_const( + ty::ConstKind::Unevaluated(ty::UnevaluatedConst::new( + obligation.predicate.def_id, + obligation.predicate.substs, + )), + tcx.type_of(obligation.predicate.def_id) + .subst(tcx, obligation.predicate.substs), + ) + .into(), + kind => { + bug!("unknown projection def-id: {}", kind.descr(obligation.predicate.def_id)) + } + }; + + Ok(Projected::NoProgress(term)) + } // Error occurred while trying to processing impls. ProjectionCandidateSet::Error(e) => Err(ProjectionError::TraitSelectionError(e)), // Inherent ambiguity that prevents us from even enumerating the diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index a019d00461be1..1db9b8ce92e4f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -11,7 +11,7 @@ use hir::LangItem; use rustc_hir as hir; use rustc_infer::traits::ObligationCause; use rustc_infer::traits::{Obligation, SelectionError, TraitObligation}; -use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, TreatProjections}; +use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use crate::traits; @@ -875,12 +875,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::Adt(..) => { - // Find a custom `impl Drop` impl, if it exists - let relevant_impl = self.tcx().find_map_relevant_impl( + let mut relevant_impl = None; + self.tcx().for_each_relevant_impl( self.tcx().require_lang_item(LangItem::Drop, None), obligation.predicate.skip_binder().trait_ref.self_ty(), - TreatProjections::ForLookup, - Some, + |impl_def_id| { + if let Some(old_impl_def_id) = relevant_impl { + self.tcx() + .sess + .struct_span_err( + self.tcx().def_span(impl_def_id), + "multiple drop impls found", + ) + .span_note(self.tcx().def_span(old_impl_def_id), "other impl here") + .delay_as_bug(); + } + + relevant_impl = Some(impl_def_id); + }, ); if let Some(impl_def_id) = relevant_impl { diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs index 73e2c2cfbbef6..587877dff552f 100644 --- a/library/core/src/array/iter.rs +++ b/library/core/src/array/iter.rs @@ -3,8 +3,9 @@ use crate::num::NonZeroUsize; use crate::{ fmt, + intrinsics::transmute_unchecked, iter::{self, ExactSizeIterator, FusedIterator, TrustedLen}, - mem::{self, MaybeUninit}, + mem::MaybeUninit, ops::{IndexRange, Range}, ptr, }; @@ -63,18 +64,11 @@ impl IntoIterator for [T; N] { // an array of `T`. // // With that, this initialization satisfies the invariants. - - // FIXME(LukasKalbertodt): actually use `mem::transmute` here, once it - // works with const generics: - // `mem::transmute::<[T; N], [MaybeUninit; N]>(array)` // - // Until then, we can use `mem::transmute_copy` to create a bitwise copy - // as a different type, then forget `array` so that it is not dropped. - unsafe { - let iter = IntoIter { data: mem::transmute_copy(&self), alive: IndexRange::zero_to(N) }; - mem::forget(self); - iter - } + // FIXME: If normal `transmute` ever gets smart enough to allow this + // directly, use it instead of `transmute_unchecked`. + let data: [MaybeUninit; N] = unsafe { transmute_unchecked(self) }; + IntoIter { data, alive: IndexRange::zero_to(N) } } } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index ba03da411e34e..39edfd8265b41 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1376,6 +1376,20 @@ extern "rust-intrinsic" { #[rustc_nounwind] pub fn transmute(src: Src) -> Dst; + /// Like [`transmute`], but even less checked at compile-time: rather than + /// giving an error for `size_of::() != size_of::()`, it's + /// **Undefined Behaviour** at runtime. + /// + /// Prefer normal `transmute` where possible, for the extra checking, since + /// both do exactly the same thing at runtime, if they both compile. + /// + /// This is not expected to ever be exposed directly to users, rather it + /// may eventually be exposed through some more-constrained API. + #[cfg(not(bootstrap))] + #[rustc_const_stable(feature = "const_transmute", since = "1.56.0")] + #[rustc_nounwind] + pub fn transmute_unchecked(src: Src) -> Dst; + /// Returns `true` if the actual type given as `T` requires drop /// glue; returns `false` if the actual type provided for `T` /// implements `Copy`. @@ -2798,3 +2812,11 @@ pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { write_bytes(dst, val, count) } } + +/// Polyfill for bootstrap +#[cfg(bootstrap)] +pub const unsafe fn transmute_unchecked(src: Src) -> Dst { + use crate::mem::*; + // SAFETY: It's a transmute -- the caller promised it's fine. + unsafe { transmute_copy(&ManuallyDrop::new(src)) } +} diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 9c6d48675a6b1..2588b7d2befac 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -945,14 +945,10 @@ impl MaybeUninit { // * `MaybeUninit` and T are guaranteed to have the same layout // * `MaybeUninit` does not drop, so there are no double-frees // And thus the conversion is safe - let ret = unsafe { + unsafe { intrinsics::assert_inhabited::<[T; N]>(); - (&array as *const _ as *const [T; N]).read() - }; - - // FIXME: required to avoid `~const Destruct` bound - super::forget(array); - ret + intrinsics::transmute_unchecked(array) + } } /// Assuming all the elements are initialized, get a slice to them. diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index e6788ee6feeca..680a8da6adf20 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -722,11 +722,14 @@ def bootstrap_binary(self): def build_bootstrap(self, color, verbose_count): """Build bootstrap""" - print("Building bootstrap") + env = os.environ.copy() + if "GITHUB_ACTIONS" in env: + print("::group::Building bootstrap") + else: + print("Building bootstrap") build_dir = os.path.join(self.build_dir, "bootstrap") if self.clean and os.path.exists(build_dir): shutil.rmtree(build_dir) - env = os.environ.copy() # `CARGO_BUILD_TARGET` breaks bootstrap build. # See also: . if "CARGO_BUILD_TARGET" in env: @@ -798,6 +801,9 @@ def build_bootstrap(self, color, verbose_count): # Run this from the source directory so cargo finds .cargo/config run(args, env=env, verbose=self.verbose, cwd=self.rust_root) + if "GITHUB_ACTIONS" in env: + print("::endgroup::") + def build_triple(self): """Build triple as in LLVM diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 44efc502e39d4..60de46ce64c15 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -105,15 +105,7 @@ impl Step for Std { cargo.arg("--lib"); } - 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); + let _guard = builder.msg_check("library artifacts", target); run_cargo( builder, cargo, @@ -167,18 +159,7 @@ impl Step for Std { cargo.arg("-p").arg(krate.name); } - 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); + let _guard = builder.msg_check("library test/bench/example targets", target); run_cargo( builder, cargo, @@ -252,15 +233,7 @@ impl Step for Rustc { cargo.arg("-p").arg(krate.name); } - 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); + let _guard = builder.msg_check("compiler artifacts", target); run_cargo( builder, cargo, @@ -317,15 +290,7 @@ impl Step for CodegenBackend { .arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend))); rustc_cargo_env(builder, &mut cargo, target, compiler.stage); - 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); + let _guard = builder.msg_check(&backend, target); run_cargo( builder, @@ -385,15 +350,7 @@ impl Step for RustAnalyzer { cargo.arg("--benches"); } - 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); + let _guard = builder.msg_check("rust-analyzer artifacts", target); run_cargo( builder, cargo, @@ -460,18 +417,7 @@ 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"); - 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); + let _guard = builder.msg_check(&concat!(stringify!($name), " artifacts").to_lowercase(), target); run_cargo( builder, cargo, diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index ab307d4d038c5..7d2a6862500a3 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -143,23 +143,13 @@ impl Step for Std { cargo.arg("-p").arg(krate); } - let msg = if compiler.host == target { - format!( - "Building{} stage{} library artifacts ({}) ", - crate_description(&self.crates), - compiler.stage, - compiler.host - ) - } else { - format!( - "Building{} stage{} library artifacts ({} -> {})", - crate_description(&self.crates), - compiler.stage, - compiler.host, - target, - ) - }; - builder.info(&msg); + let _guard = builder.msg( + Kind::Build, + compiler.stage, + format_args!("library artifacts{}", crate_description(&self.crates)), + compiler.host, + target, + ); run_cargo( builder, cargo, @@ -790,24 +780,13 @@ impl Step for Rustc { cargo.arg("-p").arg(krate); } - let msg = if compiler.host == target { - format!( - "Building{} compiler artifacts (stage{} -> stage{})", - crate_description(&self.crates), - compiler.stage, - compiler.stage + 1 - ) - } else { - format!( - "Building{} compiler artifacts (stage{}:{} -> stage{}:{})", - crate_description(&self.crates), - compiler.stage, - compiler.host, - compiler.stage + 1, - target, - ) - }; - builder.info(&msg); + let _guard = builder.msg_sysroot_tool( + Kind::Build, + compiler.stage, + format_args!("compiler artifacts{}", crate_description(&self.crates)), + compiler.host, + target, + ); run_cargo( builder, cargo, @@ -1114,15 +1093,7 @@ impl Step for CodegenBackend { let tmp_stamp = out_dir.join(".tmp.stamp"); - let msg = if compiler.host == target { - format!("Building stage{} codegen backend {}", compiler.stage, backend) - } else { - format!( - "Building stage{} codegen backend {} ({} -> {})", - compiler.stage, backend, compiler.host, target - ) - }; - builder.info(&msg); + let _guard = builder.msg_build(compiler, format_args!("codegen backend {backend}"), target); let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false, false); if builder.config.dry_run() { return; diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 42d895a3413fb..b62aa9992469b 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -12,7 +12,7 @@ use crate::util::t; use crate::dist; use crate::tarball::GeneratedTarball; -use crate::Compiler; +use crate::{Compiler, Kind}; use crate::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::config::{Config, TargetSelection}; @@ -52,7 +52,7 @@ fn install_sh( host: Option, tarball: &GeneratedTarball, ) { - builder.info(&format!("Install {} stage{} ({:?})", package, stage, host)); + let _guard = builder.msg(Kind::Install, stage, package, host, host); let prefix = default_path(&builder.config.prefix, "/usr/local"); let sysconfdir = prefix.join(default_path(&builder.config.sysconfdir, "/etc")); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index bfdb029951f29..238d167c4c276 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -19,13 +19,14 @@ use std::cell::{Cell, RefCell}; use std::collections::{HashMap, HashSet}; use std::env; +use std::fmt::Display; use std::fs::{self, File}; use std::io; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::str; -use build_helper::ci::CiEnv; +use build_helper::ci::{gha, CiEnv}; use channel::GitInfo; use config::{DryRun, Target}; use filetime::FileTime; @@ -993,6 +994,85 @@ impl Build { } } + fn msg_check( + &self, + what: impl Display, + target: impl Into>, + ) -> Option { + self.msg(Kind::Check, self.config.stage, what, self.config.build, target) + } + + fn msg_build( + &self, + compiler: Compiler, + what: impl Display, + target: impl Into>, + ) -> Option { + self.msg(Kind::Build, compiler.stage, what, compiler.host, target) + } + + /// Return a `Group` guard for a [`Step`] that is built for each `--stage`. + fn msg( + &self, + action: impl Into, + stage: u32, + what: impl Display, + host: impl Into>, + target: impl Into>, + ) -> Option { + let action = action.into(); + let msg = |fmt| format!("{action:?}ing stage{stage} {what}{fmt}"); + let msg = if let Some(target) = target.into() { + let host = host.into().unwrap(); + if host == target { + msg(format_args!(" ({target})")) + } else { + msg(format_args!(" ({host} -> {target})")) + } + } else { + msg(format_args!("")) + }; + self.group(&msg) + } + + /// Return a `Group` guard for a [`Step`] that is only built once and isn't affected by `--stage`. + fn msg_unstaged( + &self, + action: impl Into, + what: impl Display, + target: TargetSelection, + ) -> Option { + let action = action.into(); + let msg = format!("{action:?}ing {what} for {target}"); + self.group(&msg) + } + + fn msg_sysroot_tool( + &self, + action: impl Into, + stage: u32, + what: impl Display, + host: TargetSelection, + target: TargetSelection, + ) -> Option { + let action = action.into(); + let msg = |fmt| format!("{action:?}ing {what} {fmt}"); + let msg = if host == target { + msg(format_args!("(stage{stage} -> stage{}, {target})", stage + 1)) + } else { + msg(format_args!("(stage{stage}:{host} -> stage{}:{target})", stage + 1)) + }; + self.group(&msg) + } + + fn group(&self, msg: &str) -> Option { + self.info(&msg); + match self.config.dry_run { + DryRun::SelfCheck => None, + DryRun::Disabled | DryRun::UserSelected => Some(gha::group(&msg)), + } + } + /// Returns the number of parallel jobs that have been configured for this /// build. fn jobs(&self) -> u32 { diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/llvm.rs index cfc7418631368..67cb88373910c 100644 --- a/src/bootstrap/llvm.rs +++ b/src/bootstrap/llvm.rs @@ -21,7 +21,7 @@ use crate::channel; use crate::config::{Config, TargetSelection}; use crate::util::get_clang_cl_resource_dir; use crate::util::{self, exe, output, t, up_to_date}; -use crate::{CLang, GitRepo}; +use crate::{CLang, GitRepo, Kind}; use build_helper::ci::CiEnv; @@ -271,7 +271,7 @@ impl Step for Llvm { panic!("shared linking to LLVM is not currently supported on {}", target.triple); } - builder.info(&format!("Building LLVM for {}", target)); + let _guard = builder.msg_unstaged(Kind::Build, "LLVM", target); t!(stamp.remove()); let _time = util::timeit(&builder); t!(fs::create_dir_all(&out_dir)); @@ -813,7 +813,7 @@ impl Step for Lld { return out_dir; } - builder.info(&format!("Building LLD for {}", target)); + let _guard = builder.msg_unstaged(Kind::Build, "LLD", target); let _time = util::timeit(&builder); t!(fs::create_dir_all(&out_dir)); @@ -911,7 +911,7 @@ impl Step for Sanitizers { return runtimes; } - builder.info(&format!("Building sanitizers for {}", self.target)); + let _guard = builder.msg_unstaged(Kind::Build, "sanitizers", self.target); t!(stamp.remove()); let _time = util::timeit(&builder); @@ -1103,7 +1103,7 @@ impl Step for CrtBeginEnd { return out_dir; } - builder.info("Building crtbegin.o and crtend.o"); + let _guard = builder.msg_unstaged(Kind::Build, "crtbegin.o and crtend.o", self.target); t!(fs::create_dir_all(&out_dir)); let mut cfg = cc::Build::new(); @@ -1168,7 +1168,7 @@ impl Step for Libunwind { return out_dir; } - builder.info(&format!("Building libunwind.a for {}", self.target.triple)); + let _guard = builder.msg_unstaged(Kind::Build, "libunwind.a", self.target); t!(fs::create_dir_all(&out_dir)); let mut cc_cfg = cc::Build::new(); diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index ccf83974b8c2f..601351ea8e3c0 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -5,7 +5,6 @@ use std::env; use std::ffi::OsString; -use std::fmt; use std::fs; use std::iter; use std::path::{Path, PathBuf}; @@ -57,12 +56,12 @@ impl TestKind { } } -impl fmt::Display for TestKind { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(match *self { - TestKind::Test => "Testing", - TestKind::Bench => "Benchmarking", - }) +impl Into for TestKind { + fn into(self) -> Kind { + match self { + TestKind::Test => Kind::Test, + TestKind::Bench => Kind::Bench, + } } } @@ -1905,7 +1904,13 @@ impl BookTest { rustbook_cmd.env("RUSTC_BOOTSTRAP", "1"); rustbook_cmd.env("PATH", new_path).arg("test").arg(path); builder.add_rust_test_threads(&mut rustbook_cmd); - builder.info(&format!("Testing rustbook {}", self.path.display())); + let _guard = builder.msg( + Kind::Test, + compiler.stage, + format_args!("rustbook {}", self.path.display()), + compiler.host, + compiler.host, + ); let _time = util::timeit(&builder); let toolstate = if try_run(builder, &mut rustbook_cmd) { ToolState::TestPass @@ -2033,7 +2038,8 @@ impl Step for ErrorIndex { let mut tool = tool::ErrorIndex::command(builder); tool.arg("markdown").arg(&output); - builder.info(&format!("Testing error-index stage{}", compiler.stage)); + let _guard = + builder.msg(Kind::Test, compiler.stage, "error-index", compiler.host, compiler.host); let _time = util::timeit(&builder); builder.run_quiet(&mut tool); // The tests themselves need to link to std, so make sure it is @@ -2263,14 +2269,13 @@ impl Step for Crate { ); } - builder.info(&format!( - "{}{} stage{} ({} -> {})", + let _guard = builder.msg( test_kind, - crate_description(&self.crates), compiler.stage, - &compiler.host, - target - )); + crate_description(&self.crates), + compiler.host, + target, + ); let _time = util::timeit(&builder); crate::render_tests::try_run_tests(builder, &mut cargo.into()); } @@ -2386,10 +2391,8 @@ impl Step for CrateRustdoc { cargo.arg("--quiet"); } - builder.info(&format!( - "{} rustdoc stage{} ({} -> {})", - test_kind, compiler.stage, &compiler.host, target - )); + let _guard = builder.msg(test_kind, compiler.stage, "rustdoc", compiler.host, target); + let _time = util::timeit(&builder); add_flags_and_try_run_tests(builder, &mut cargo.into()); @@ -2453,10 +2456,8 @@ impl Step for CrateRustdocJsonTypes { cargo.arg("'-Ctarget-feature=-crt-static'"); } - builder.info(&format!( - "{} rustdoc-json-types stage{} ({} -> {})", - test_kind, compiler.stage, &compiler.host, target - )); + let _guard = + builder.msg(test_kind, compiler.stage, "rustdoc-json-types", compiler.host, target); let _time = util::timeit(&builder); add_flags_and_try_run_tests(builder, &mut cargo.into()); @@ -2845,7 +2846,7 @@ impl Step for TestHelpers { return; } - builder.info("Building test helpers"); + let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target); t!(fs::create_dir_all(&dst)); let mut cfg = cc::Build::new(); // FIXME: Workaround for https://github.com/emscripten-core/emscripten/issues/9013 diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index f8da6df0c7ccd..f3724b2c0e4cd 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -11,6 +11,7 @@ use crate::toolstate::ToolState; use crate::util::{add_dylib_path, exe, t}; use crate::Compiler; use crate::Mode; +use crate::{gha, Kind}; #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub enum SourceType { @@ -32,41 +33,27 @@ struct ToolBuild { allow_features: &'static str, } -fn tooling_output( - mode: Mode, - tool: &str, - build_stage: u32, - host: &TargetSelection, - target: &TargetSelection, -) -> String { - match mode { - // depends on compiler stage, different to host compiler - Mode::ToolRustc => { - if host == target { - format!("Building tool {} (stage{} -> stage{})", tool, build_stage, build_stage + 1) - } else { - format!( - "Building tool {} (stage{}:{} -> stage{}:{})", - tool, - build_stage, - host, - build_stage + 1, - target - ) - } - } - // doesn't depend on compiler, same as host compiler - Mode::ToolStd => { - if host == target { - format!("Building tool {} (stage{})", tool, build_stage) - } else { - format!( - "Building tool {} (stage{}:{} -> stage{}:{})", - tool, build_stage, host, build_stage, target - ) - } +impl Builder<'_> { + fn msg_tool( + &self, + mode: Mode, + tool: &str, + build_stage: u32, + host: &TargetSelection, + target: &TargetSelection, + ) -> Option { + match mode { + // depends on compiler stage, different to host compiler + Mode::ToolRustc => self.msg_sysroot_tool( + Kind::Build, + build_stage, + format_args!("tool {tool}"), + *host, + *target, + ), + // doesn't depend on compiler, same as host compiler + _ => self.msg(Kind::Build, build_stage, format_args!("tool {tool}"), *host, *target), } - _ => format!("Building tool {} (stage{})", tool, build_stage), } } @@ -111,14 +98,13 @@ impl Step for ToolBuild { if !self.allow_features.is_empty() { cargo.allow_features(self.allow_features); } - let msg = tooling_output( + let _guard = builder.msg_tool( self.mode, self.tool, self.compiler.stage, &self.compiler.host, &self.target, ); - builder.info(&msg); let mut cargo = Command::from(cargo); let is_expected = builder.try_run(&mut cargo); @@ -492,14 +478,13 @@ impl Step for Rustdoc { cargo.rustflag("--cfg=parallel_compiler"); } - let msg = tooling_output( + let _guard = builder.msg_tool( Mode::ToolRustc, "rustdoc", build_compiler.stage, &self.compiler.host, &target, ); - builder.info(&msg); builder.run(&mut cargo.into()); // Cargo adds a number of paths to the dylib search path on windows, which results in diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 33e80df9ed77b..f2486abaaa77e 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -13,7 +13,7 @@ use rustc_hir::def::Namespace::*; use rustc_hir::def::{DefKind, Namespace, PerNS}; use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; use rustc_hir::Mutability; -use rustc_middle::ty::{fast_reject::TreatProjections, Ty, TyCtxt}; +use rustc_middle::ty::{Ty, TyCtxt}; use rustc_middle::{bug, ty}; use rustc_resolve::rustdoc::{has_primitive_or_keyword_docs, prepare_to_doc_link_resolution}; use rustc_resolve::rustdoc::{strip_generics_from_path, MalformedGenerics}; @@ -772,11 +772,10 @@ fn trait_impls_for<'a>( module: DefId, ) -> FxHashSet<(DefId, DefId)> { let tcx = cx.tcx; - let iter = tcx.doc_link_traits_in_scope(module).iter().flat_map(|&trait_| { - trace!("considering explicit impl for trait {:?}", trait_); + let mut impls = FxHashSet::default(); - // Look at each trait implementation to see if it's an impl for `did` - tcx.find_map_relevant_impl(trait_, ty, TreatProjections::ForLookup, |impl_| { + for &trait_ in tcx.doc_link_traits_in_scope(module) { + tcx.for_each_relevant_impl(trait_, ty, |impl_| { let trait_ref = tcx.impl_trait_ref(impl_).expect("this is not an inherent impl"); // Check if these are the same type. let impl_type = trait_ref.skip_binder().self_ty(); @@ -800,10 +799,13 @@ fn trait_impls_for<'a>( _ => false, }; - if saw_impl { Some((impl_, trait_)) } else { None } - }) - }); - iter.collect() + if saw_impl { + impls.insert((impl_, trait_)); + } + }); + } + + impls } /// Check for resolve collisions between a trait and its derive. diff --git a/src/tools/build_helper/src/ci.rs b/src/tools/build_helper/src/ci.rs index 9f113c72b9338..d2e9c324af8c6 100644 --- a/src/tools/build_helper/src/ci.rs +++ b/src/tools/build_helper/src/ci.rs @@ -38,3 +38,27 @@ impl CiEnv { } } } + +pub mod gha { + /// All github actions log messages from this call to the Drop of the return value + /// will be grouped and hidden by default in logs. Note that nesting these does + /// not really work. + pub fn group(name: impl std::fmt::Display) -> Group { + if std::env::var_os("GITHUB_ACTIONS").is_some() { + eprintln!("::group::{name}"); + } + Group(()) + } + + /// A guard that closes the current github actions log group on drop. + #[must_use] + pub struct Group(()); + + impl Drop for Group { + fn drop(&mut self) { + if std::env::var_os("GITHUB_ACTIONS").is_some() { + eprintln!("::endgroup::"); + } + } + } +} diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs index 51c000b82ea8a..664e697c2a5d2 100644 --- a/tests/codegen/intrinsics/transmute.rs +++ b/tests/codegen/intrinsics/transmute.rs @@ -8,10 +8,10 @@ #![feature(inline_const)] #![allow(unreachable_code)] -use std::mem::{transmute, MaybeUninit}; +use std::mem::MaybeUninit; +use std::intrinsics::{transmute, transmute_unchecked}; -// Some of the cases here are statically rejected by `mem::transmute`, so -// we need to generate custom MIR for those cases to get to codegen. +// Some of these need custom MIR to not get removed by MIR optimizations. use std::intrinsics::mir::*; enum Never {} @@ -30,59 +30,35 @@ pub struct Aggregate8(u8); // CHECK-LABEL: @check_bigger_size( #[no_mangle] -#[custom_mir(dialect = "runtime", phase = "initial")] pub unsafe fn check_bigger_size(x: u16) -> u32 { // CHECK: call void @llvm.trap - mir!{ - { - RET = CastTransmute(x); - Return() - } - } + transmute_unchecked(x) } // CHECK-LABEL: @check_smaller_size( #[no_mangle] -#[custom_mir(dialect = "runtime", phase = "initial")] pub unsafe fn check_smaller_size(x: u32) -> u16 { // CHECK: call void @llvm.trap - mir!{ - { - RET = CastTransmute(x); - Return() - } - } + transmute_unchecked(x) } // CHECK-LABEL: @check_smaller_array( #[no_mangle] -#[custom_mir(dialect = "runtime", phase = "initial")] pub unsafe fn check_smaller_array(x: [u32; 7]) -> [u32; 3] { // CHECK: call void @llvm.trap - mir!{ - { - RET = CastTransmute(x); - Return() - } - } + transmute_unchecked(x) } // CHECK-LABEL: @check_bigger_array( #[no_mangle] -#[custom_mir(dialect = "runtime", phase = "initial")] pub unsafe fn check_bigger_array(x: [u32; 3]) -> [u32; 7] { // CHECK: call void @llvm.trap - mir!{ - { - RET = CastTransmute(x); - Return() - } - } + transmute_unchecked(x) } // CHECK-LABEL: @check_to_uninhabited( #[no_mangle] -#[custom_mir(dialect = "runtime", phase = "initial")] +#[custom_mir(dialect = "runtime", phase = "optimized")] pub unsafe fn check_to_uninhabited(x: u16) -> BigNever { // CHECK: call void @llvm.trap mir!{ @@ -95,7 +71,7 @@ pub unsafe fn check_to_uninhabited(x: u16) -> BigNever { // CHECK-LABEL: @check_from_uninhabited( #[no_mangle] -#[custom_mir(dialect = "runtime", phase = "initial")] +#[custom_mir(dialect = "runtime", phase = "optimized")] pub unsafe fn check_from_uninhabited(x: BigNever) -> u16 { // CHECK: ret i16 poison mir!{ diff --git a/tests/ui/associated-consts/projection-unspecified-but-bounded.rs b/tests/ui/associated-consts/projection-unspecified-but-bounded.rs new file mode 100644 index 0000000000000..b1a0f39962b61 --- /dev/null +++ b/tests/ui/associated-consts/projection-unspecified-but-bounded.rs @@ -0,0 +1,16 @@ +#![feature(associated_const_equality)] + +// Issue 110549 + +pub trait TraitWAssocConst { + const A: usize; +} + +fn foo>() {} + +fn bar() { + foo::(); + //~^ ERROR type mismatch resolving `::A == 32` +} + +fn main() {} diff --git a/tests/ui/associated-consts/projection-unspecified-but-bounded.stderr b/tests/ui/associated-consts/projection-unspecified-but-bounded.stderr new file mode 100644 index 0000000000000..8175e510a093f --- /dev/null +++ b/tests/ui/associated-consts/projection-unspecified-but-bounded.stderr @@ -0,0 +1,17 @@ +error[E0271]: type mismatch resolving `::A == 32` + --> $DIR/projection-unspecified-but-bounded.rs:12:11 + | +LL | foo::(); + | ^ expected `32`, found `::A` + | + = note: expected constant `32` + found constant `::A` +note: required by a bound in `foo` + --> $DIR/projection-unspecified-but-bounded.rs:9:28 + | +LL | fn foo>() {} + | ^^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/proc-macro/test-same-crate.rs b/tests/ui/proc-macro/test-same-crate.rs new file mode 100644 index 0000000000000..c13f384fa3ae1 --- /dev/null +++ b/tests/ui/proc-macro/test-same-crate.rs @@ -0,0 +1,16 @@ +// compile-flags: --test +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn mac(input: TokenStream) -> TokenStream { loop {} } + +#[cfg(test)] +mod test { + #[test] + fn t() { crate::mac!(A) } + //~^ ERROR can't use a procedural macro from the same crate that defines it + //~| HELP you can define integration tests in a directory named `tests` +} diff --git a/tests/ui/proc-macro/test-same-crate.stderr b/tests/ui/proc-macro/test-same-crate.stderr new file mode 100644 index 0000000000000..5d12e149c3c4c --- /dev/null +++ b/tests/ui/proc-macro/test-same-crate.stderr @@ -0,0 +1,10 @@ +error: can't use a procedural macro from the same crate that defines it + --> $DIR/test-same-crate.rs:13:14 + | +LL | fn t() { crate::mac!(A) } + | ^^^^^^^^^^ + | + = help: you can define integration tests in a directory named `tests` + +error: aborting due to previous error +