diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index 183e9ddf8bf98..db874afe1ab9b 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -197,7 +197,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { /// `[T]` becomes `T`, while `str` and `Trait` turn into `i8` - this /// is useful for indexing slices, as `&[T]`'s data pointer is `T*`. /// If the type is an unsized struct, the regular layout is generated, - /// with the inner-most trailing unsized field using the "minimal unit" + /// with the innermost trailing unsized field using the "minimal unit" /// of that field's type - this is useful for taking the address of /// that field and ensuring the struct has the right alignment. fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> { diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 1af666f818bba..6be4c3f034f12 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -191,7 +191,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { /// `[T]` becomes `T`, while `str` and `Trait` turn into `i8` - this /// is useful for indexing slices, as `&[T]`'s data pointer is `T*`. /// If the type is an unsized struct, the regular layout is generated, - /// with the inner-most trailing unsized field using the "minimal unit" + /// with the innermost trailing unsized field using the "minimal unit" /// of that field's type - this is useful for taking the address of /// that field and ensuring the struct has the right alignment. fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type { diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index f3d9a7d37e6cc..a726ee73aaa26 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -888,7 +888,7 @@ impl CrateInfo { // below. // // In order to get this left-to-right dependency ordering, we use the reverse - // postorder of all crates putting the leaves at the right-most positions. + // postorder of all crates putting the leaves at the rightmost positions. let mut compiler_builtins = None; let mut used_crates: Vec<_> = tcx .postorder_cnums(()) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 1adb6b9dcfee3..0ccc71ae06c45 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -58,9 +58,9 @@ impl HumanReadableErrorType { struct Margin { /// The available whitespace in the left that can be consumed when centering. pub whitespace_left: usize, - /// The column of the beginning of left-most span. + /// The column of the beginning of leftmost span. pub span_left: usize, - /// The column of the end of right-most span. + /// The column of the end of rightmost span. pub span_right: usize, /// The beginning of the line to be displayed. pub computed_left: usize, @@ -128,7 +128,7 @@ impl Margin { } else { 0 }; - // We want to show as much as possible, max_line_len is the right-most boundary for the + // We want to show as much as possible, max_line_len is the rightmost boundary for the // relevant code. self.computed_right = max(max_line_len, self.computed_left); @@ -685,7 +685,7 @@ impl HumanEmitter { buffer.puts(line_offset, code_offset, "...", Style::LineNumber); } if margin.was_cut_right(line_len) { - // We have stripped some code after the right-most span end, make it clear we did so. + // We have stripped some code after the rightmost span end, make it clear we did so. buffer.puts(line_offset, code_offset + taken - 3, "...", Style::LineNumber); } buffer.puts(line_offset, 0, &self.maybe_anonymized(line_index), Style::LineNumber); diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 57bac9d09d5ec..fcf3352bfc597 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -25,7 +25,7 @@ expand_collapse_debuginfo_illegal = illegal value for attribute #[collapse_debuginfo(no|external|yes)] expand_count_repetition_misplaced = - `count` can not be placed inside the inner-most repetition + `count` can not be placed inside the innermost repetition expand_crate_name_in_cfg_attr = `crate_name` within an `#![cfg_attr]` attribute is forbidden diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index c4ba98f581e49..810a5d30c7ec4 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -23,11 +23,11 @@ pub(crate) enum MetaVarExpr { /// Ignore a meta-variable for repetition without expansion. Ignore(Ident), - /// The index of the repetition at a particular depth, where 0 is the inner-most + /// The index of the repetition at a particular depth, where 0 is the innermost /// repetition. The `usize` is the depth. Index(usize), - /// The length of the repetition at a particular depth, where 0 is the inner-most + /// The length of the repetition at a particular depth, where 0 is the innermost /// repetition. The `usize` is the depth. Len(usize), } diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index fb6fe0bb1d77b..34811ca2b3566 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -570,7 +570,7 @@ fn lockstep_iter_size( } } -/// Used solely by the `count` meta-variable expression, counts the outer-most repetitions at a +/// Used solely by the `count` meta-variable expression, counts the outermost repetitions at a /// given optional nested depth. /// /// For example, a macro parameter of `$( { $( $foo:ident ),* } )*` called with `{ a, b } { c }`: diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 534458046945c..6f9d638b85e6a 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -364,6 +364,8 @@ declare_features! ( (accepted, self_in_typedefs, "1.32.0", Some(49303)), /// Allows `Self` struct constructor (RFC 2302). (accepted, self_struct_ctor, "1.32.0", Some(51994)), + /// Shortern the tail expression lifetime + (accepted, shorter_tail_lifetimes, "CURRENT_RUSTC_VERSION", Some(123739)), /// Allows using subslice patterns, `[a, .., b]` and `[a, xs @ .., b]`. (accepted, slice_patterns, "1.42.0", Some(62254)), /// Allows use of `&foo[a..b]` as a slicing syntax. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 0606f2914c341..ee7a88965a57b 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -613,8 +613,6 @@ declare_features! ( (unstable, rust_cold_cc, "1.63.0", Some(97544)), /// Allows use of x86 SHA512, SM3 and SM4 target-features and intrinsics (unstable, sha512_sm_x86, "1.82.0", Some(126624)), - /// Shortern the tail expression lifetime - (unstable, shorter_tail_lifetimes, "1.79.0", Some(123739)), /// Allows the use of SIMD types in functions declared in `extern` blocks. (unstable, simd_ffi, "1.0.0", Some(27731)), /// Allows specialization of implementations (RFC 1210). 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 75956165e8737..fc5ec31cda80c 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -43,14 +43,13 @@ mod refine; /// - `impl_m`: type of the method we are checking /// - `trait_m`: the method in the trait /// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation +#[instrument(level = "debug", skip(tcx))] pub(super) fn compare_impl_method<'tcx>( tcx: TyCtxt<'tcx>, impl_m: ty::AssocItem, trait_m: ty::AssocItem, impl_trait_ref: ty::TraitRef<'tcx>, ) { - debug!("compare_impl_method(impl_trait_ref={:?})", impl_trait_ref); - let _: Result<_, ErrorGuaranteed> = try { check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, false)?; compare_method_predicate_entailment(tcx, impl_m, trait_m, impl_trait_ref)?; @@ -167,8 +166,6 @@ fn compare_method_predicate_entailment<'tcx>( trait_m: ty::AssocItem, impl_trait_ref: ty::TraitRef<'tcx>, ) -> Result<(), ErrorGuaranteed> { - let trait_to_impl_args = impl_trait_ref.args; - // This node-id should be used for the `body_id` field on each // `ObligationCause` (and the `FnCtxt`). // @@ -183,27 +180,17 @@ fn compare_method_predicate_entailment<'tcx>( kind: impl_m.kind, }); - // Create mapping from impl to placeholder. - let impl_to_placeholder_args = GenericArgs::identity_for_item(tcx, impl_m.def_id); - - // Create mapping from trait to placeholder. - let trait_to_placeholder_args = - impl_to_placeholder_args.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_args); - debug!("compare_impl_method: trait_to_placeholder_args={:?}", trait_to_placeholder_args); + // Create mapping from trait method to impl method. + let trait_to_impl_args = GenericArgs::identity_for_item(tcx, impl_m.def_id).rebase_onto( + tcx, + impl_m.container_id(tcx), + impl_trait_ref.args, + ); + debug!(?trait_to_impl_args); let impl_m_predicates = tcx.predicates_of(impl_m.def_id); let trait_m_predicates = tcx.predicates_of(trait_m.def_id); - // Create obligations for each predicate declared by the impl - // definition in the context of the trait's parameter - // environment. We can't just use `impl_env.caller_bounds`, - // however, because we want to replace all late-bound regions with - // region variables. - let impl_predicates = tcx.predicates_of(impl_m_predicates.parent.unwrap()); - let mut hybrid_preds = impl_predicates.instantiate_identity(tcx); - - debug!("compare_impl_method: impl_bounds={:?}", hybrid_preds); - // This is the only tricky bit of the new way we check implementation methods // We need to build a set of predicates where only the method-level bounds // are from the trait and we assume all other bounds from the implementation @@ -211,25 +198,25 @@ fn compare_method_predicate_entailment<'tcx>( // // We then register the obligations from the impl_m and check to see // if all constraints hold. - hybrid_preds.predicates.extend( - trait_m_predicates - .instantiate_own(tcx, trait_to_placeholder_args) - .map(|(predicate, _)| predicate), + let impl_predicates = tcx.predicates_of(impl_m_predicates.parent.unwrap()); + let mut hybrid_preds = impl_predicates.instantiate_identity(tcx).predicates; + hybrid_preds.extend( + trait_m_predicates.instantiate_own(tcx, trait_to_impl_args).map(|(predicate, _)| predicate), ); - // Construct trait parameter environment and then shift it into the placeholder viewpoint. - // The key step here is to update the caller_bounds's predicates to be - // the new hybrid bounds we computed. let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_def_id); - let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing); + let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds), Reveal::UserFacing); let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause); + debug!(caller_bounds=?param_env.caller_bounds()); let infcx = &tcx.infer_ctxt().build(); let ocx = ObligationCtxt::new_with_diagnostics(infcx); - debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds()); - - let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_args); + // Create obligations for each predicate declared by the impl + // definition in the context of the hybrid param-env. This makes + // sure that the impl's method's where clauses are not more + // restrictive than the trait's method (and the impl itself). + let impl_m_own_bounds = impl_m_predicates.instantiate_own_identity(); for (predicate, span) in impl_m_own_bounds { let normalize_cause = traits::ObligationCause::misc(span, impl_m_def_id); let predicate = ocx.normalize(&normalize_cause, param_env, predicate); @@ -256,7 +243,6 @@ fn compare_method_predicate_entailment<'tcx>( // any associated types appearing in the fn arguments or return // type. - // Compute placeholder form of impl and trait method tys. let mut wf_tys = FxIndexSet::default(); let unnormalized_impl_sig = infcx.instantiate_binder_with_fresh_vars( @@ -267,9 +253,9 @@ fn compare_method_predicate_entailment<'tcx>( let norm_cause = ObligationCause::misc(impl_m_span, impl_m_def_id); let impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_impl_sig); - debug!("compare_impl_method: impl_fty={:?}", impl_sig); + debug!(?impl_sig); - let trait_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_placeholder_args); + let trait_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_impl_args); let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig); // Next, add all inputs and output as well-formed tys. Importantly, @@ -280,9 +266,7 @@ fn compare_method_predicate_entailment<'tcx>( // We also have to add the normalized trait signature // as we don't normalize during implied bounds computation. wf_tys.extend(trait_sig.inputs_and_output.iter()); - let trait_fty = Ty::new_fn_ptr(tcx, ty::Binder::dummy(trait_sig)); - - debug!("compare_impl_method: trait_fty={:?}", trait_fty); + debug!(?trait_sig); // FIXME: We'd want to keep more accurate spans than "the method signature" when // processing the comparison between the trait and impl fn, but we sadly lose them @@ -455,8 +439,6 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( // just so we don't ICE during instantiation later. check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?; - let trait_to_impl_args = impl_trait_ref.args; - let impl_m_hir_id = tcx.local_def_id_to_hir_id(impl_m_def_id); let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span(); let cause = @@ -466,18 +448,18 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( kind: impl_m.kind, }); - // Create mapping from impl to placeholder. - let impl_to_placeholder_args = GenericArgs::identity_for_item(tcx, impl_m.def_id); - - // Create mapping from trait to placeholder. - let trait_to_placeholder_args = - impl_to_placeholder_args.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_args); + // Create mapping from trait to impl (i.e. impl trait header + impl method identity args). + let trait_to_impl_args = GenericArgs::identity_for_item(tcx, impl_m.def_id).rebase_onto( + tcx, + impl_m.container_id(tcx), + impl_trait_ref.args, + ); let hybrid_preds = tcx .predicates_of(impl_m.container_id(tcx)) .instantiate_identity(tcx) .into_iter() - .chain(tcx.predicates_of(trait_m.def_id).instantiate_own(tcx, trait_to_placeholder_args)) + .chain(tcx.predicates_of(trait_m.def_id).instantiate_own(tcx, trait_to_impl_args)) .map(|(clause, _)| clause); let param_env = ty::ParamEnv::new(tcx.mk_clauses_from_iter(hybrid_preds), Reveal::UserFacing); let param_env = traits::normalize_param_env_or_error( @@ -511,7 +493,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( .instantiate_binder_with_fresh_vars( return_span, infer::HigherRankedType, - tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_placeholder_args), + tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_impl_args), ) .fold_with(&mut collector); @@ -705,7 +687,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( // Also, we only need to account for a difference in trait and impl args, // since we previously enforce that the trait method and impl method have the // same generics. - let num_trait_args = trait_to_impl_args.len(); + let num_trait_args = impl_trait_ref.args.len(); let num_impl_args = tcx.generics_of(impl_m.container_id(tcx)).own_params.len(); let ty = match ty.try_fold_with(&mut RemapHiddenTyRegions { tcx, @@ -1041,12 +1023,7 @@ fn check_region_bounds_on_impl_item<'tcx>( let trait_generics = tcx.generics_of(trait_m.def_id); let trait_params = trait_generics.own_counts().lifetimes; - debug!( - "check_region_bounds_on_impl_item: \ - trait_generics={:?} \ - impl_generics={:?}", - trait_generics, impl_generics - ); + debug!(?trait_generics, ?impl_generics); // Must have same number of early-bound lifetime parameters. // Unfortunately, if the user screws up the bounds, then this @@ -1710,8 +1687,7 @@ pub(super) fn compare_impl_const_raw( let trait_const_item = tcx.associated_item(trait_const_item_def); let impl_trait_ref = tcx.impl_trait_ref(impl_const_item.container_id(tcx)).unwrap().instantiate_identity(); - - debug!("compare_impl_const(impl_trait_ref={:?})", impl_trait_ref); + debug!(?impl_trait_ref); compare_number_of_generics(tcx, impl_const_item, trait_const_item, false)?; compare_generic_param_kinds(tcx, impl_const_item, trait_const_item, false)?; @@ -1722,6 +1698,7 @@ pub(super) fn compare_impl_const_raw( /// The equivalent of [compare_method_predicate_entailment], but for associated constants /// instead of associated functions. // FIXME(generic_const_items): If possible extract the common parts of `compare_{type,const}_predicate_entailment`. +#[instrument(level = "debug", skip(tcx))] fn compare_const_predicate_entailment<'tcx>( tcx: TyCtxt<'tcx>, impl_ct: ty::AssocItem, @@ -1736,13 +1713,14 @@ fn compare_const_predicate_entailment<'tcx>( // because we shouldn't really have to deal with lifetimes or // predicates. In fact some of this should probably be put into // shared functions because of DRY violations... - let impl_args = GenericArgs::identity_for_item(tcx, impl_ct.def_id); - let trait_to_impl_args = - impl_args.rebase_onto(tcx, impl_ct.container_id(tcx), impl_trait_ref.args); + let trait_to_impl_args = GenericArgs::identity_for_item(tcx, impl_ct.def_id).rebase_onto( + tcx, + impl_ct.container_id(tcx), + impl_trait_ref.args, + ); // Create a parameter environment that represents the implementation's - // method. - // Compute placeholder form of impl and trait const tys. + // associated const. let impl_ty = tcx.type_of(impl_ct_def_id).instantiate_identity(); let trait_ty = tcx.type_of(trait_ct.def_id).instantiate(tcx, trait_to_impl_args); @@ -1759,14 +1737,14 @@ fn compare_const_predicate_entailment<'tcx>( // The predicates declared by the impl definition, the trait and the // associated const in the trait are assumed. let impl_predicates = tcx.predicates_of(impl_ct_predicates.parent.unwrap()); - let mut hybrid_preds = impl_predicates.instantiate_identity(tcx); - hybrid_preds.predicates.extend( + let mut hybrid_preds = impl_predicates.instantiate_identity(tcx).predicates; + hybrid_preds.extend( trait_ct_predicates .instantiate_own(tcx, trait_to_impl_args) .map(|(predicate, _)| predicate), ); - let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing); + let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds), Reveal::UserFacing); let param_env = traits::normalize_param_env_or_error( tcx, param_env, @@ -1776,7 +1754,7 @@ fn compare_const_predicate_entailment<'tcx>( let infcx = tcx.infer_ctxt().build(); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); - let impl_ct_own_bounds = impl_ct_predicates.instantiate_own(tcx, impl_args); + let impl_ct_own_bounds = impl_ct_predicates.instantiate_own_identity(); for (predicate, span) in impl_ct_own_bounds { let cause = ObligationCause::misc(span, impl_ct_def_id); let predicate = ocx.normalize(&cause, param_env, predicate); @@ -1787,20 +1765,15 @@ fn compare_const_predicate_entailment<'tcx>( // There is no "body" here, so just pass dummy id. let impl_ty = ocx.normalize(&cause, param_env, impl_ty); - - debug!("compare_const_impl: impl_ty={:?}", impl_ty); + debug!(?impl_ty); let trait_ty = ocx.normalize(&cause, param_env, trait_ty); - - debug!("compare_const_impl: trait_ty={:?}", trait_ty); + debug!(?trait_ty); let err = ocx.sup(&cause, param_env, trait_ty, impl_ty); if let Err(terr) = err { - debug!( - "checking associated const for compatibility: impl ty {:?}, trait ty {:?}", - impl_ty, trait_ty - ); + debug!(?impl_ty, ?trait_ty); // Locate the Span containing just the type of the offending impl let (ty, _) = tcx.hir().expect_impl_item(impl_ct_def_id).expect_const(); @@ -1845,14 +1818,13 @@ fn compare_const_predicate_entailment<'tcx>( ocx.resolve_regions_and_report_errors(impl_ct_def_id, &outlives_env) } +#[instrument(level = "debug", skip(tcx))] pub(super) fn compare_impl_ty<'tcx>( tcx: TyCtxt<'tcx>, impl_ty: ty::AssocItem, trait_ty: ty::AssocItem, impl_trait_ref: ty::TraitRef<'tcx>, ) { - debug!("compare_impl_type(impl_trait_ref={:?})", impl_trait_ref); - let _: Result<(), ErrorGuaranteed> = try { compare_number_of_generics(tcx, impl_ty, trait_ty, false)?; compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?; @@ -1864,20 +1836,23 @@ pub(super) fn compare_impl_ty<'tcx>( /// The equivalent of [compare_method_predicate_entailment], but for associated types /// instead of associated functions. +#[instrument(level = "debug", skip(tcx))] fn compare_type_predicate_entailment<'tcx>( tcx: TyCtxt<'tcx>, impl_ty: ty::AssocItem, trait_ty: ty::AssocItem, impl_trait_ref: ty::TraitRef<'tcx>, ) -> Result<(), ErrorGuaranteed> { - let impl_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id); - let trait_to_impl_args = - impl_args.rebase_onto(tcx, impl_ty.container_id(tcx), impl_trait_ref.args); + let trait_to_impl_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id).rebase_onto( + tcx, + impl_ty.container_id(tcx), + impl_trait_ref.args, + ); let impl_ty_predicates = tcx.predicates_of(impl_ty.def_id); let trait_ty_predicates = tcx.predicates_of(trait_ty.def_id); - let impl_ty_own_bounds = impl_ty_predicates.instantiate_own(tcx, impl_args); + let impl_ty_own_bounds = impl_ty_predicates.instantiate_own_identity(); if impl_ty_own_bounds.len() == 0 { // Nothing to check. return Ok(()); @@ -1887,29 +1862,29 @@ fn compare_type_predicate_entailment<'tcx>( // `ObligationCause` (and the `FnCtxt`). This is what // `regionck_item` expects. let impl_ty_def_id = impl_ty.def_id.expect_local(); - debug!("compare_type_predicate_entailment: trait_to_impl_args={:?}", trait_to_impl_args); + debug!(?trait_to_impl_args); // The predicates declared by the impl definition, the trait and the // associated type in the trait are assumed. let impl_predicates = tcx.predicates_of(impl_ty_predicates.parent.unwrap()); - let mut hybrid_preds = impl_predicates.instantiate_identity(tcx); - hybrid_preds.predicates.extend( + let mut hybrid_preds = impl_predicates.instantiate_identity(tcx).predicates; + hybrid_preds.extend( trait_ty_predicates .instantiate_own(tcx, trait_to_impl_args) .map(|(predicate, _)| predicate), ); - - debug!("compare_type_predicate_entailment: bounds={:?}", hybrid_preds); + debug!(?hybrid_preds); let impl_ty_span = tcx.def_span(impl_ty_def_id); let normalize_cause = ObligationCause::misc(impl_ty_span, impl_ty_def_id); - let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing); + + let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds), Reveal::UserFacing); let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause); + debug!(caller_bounds=?param_env.caller_bounds()); + let infcx = tcx.infer_ctxt().build(); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); - debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds()); - for (predicate, span) in impl_ty_own_bounds { let cause = ObligationCause::misc(span, impl_ty_def_id); let predicate = ocx.normalize(&cause, param_env, predicate); @@ -2009,11 +1984,11 @@ pub(super) fn check_type_bounds<'tcx>( .explicit_item_bounds(trait_ty.def_id) .iter_instantiated_copied(tcx, rebased_args) .map(|(concrete_ty_bound, span)| { - debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound); + debug!(?concrete_ty_bound); traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound) }) .collect(); - debug!("check_type_bounds: item_bounds={:?}", obligations); + debug!(item_bounds=?obligations); // Normalize predicates with the assumption that the GAT may always normalize // to its definition type. This should be the param-env we use to *prove* the @@ -2032,7 +2007,7 @@ pub(super) fn check_type_bounds<'tcx>( } else { ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate) }; - debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate); + debug!(?normalized_predicate); obligation.predicate = normalized_predicate; ocx.register_obligation(obligation); diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 1a5f465981287..2ada0372d4658 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -167,9 +167,7 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h } } if let Some(tail_expr) = blk.expr { - if visitor.tcx.features().shorter_tail_lifetimes - && blk.span.edition().at_least_rust_2024() - { + if blk.span.edition().at_least_rust_2024() { visitor.terminating_scopes.insert(tail_expr.hir_id.local_id); } visitor.visit_expr(tail_expr); diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 63cf483aa2274..308e7f98f424b 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -2457,7 +2457,7 @@ fn truncate_capture_for_optimization( ) -> (Place<'_>, ty::UpvarCapture) { let is_shared_ref = |ty: Ty<'_>| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Not)); - // Find the right-most deref (if any). All the projections that come after this + // Find the rightmost deref (if any). All the projections that come after this // are fields or other "in-place pointer adjustments"; these refer therefore to // data owned by whatever pointer is being dereferenced here. let idx = place.projections.iter().rposition(|proj| ProjectionKind::Deref == proj.kind); diff --git a/compiler/rustc_lint/src/tail_expr_drop_order.rs b/compiler/rustc_lint/src/tail_expr_drop_order.rs index 44a36142ed480..89763059877c0 100644 --- a/compiler/rustc_lint/src/tail_expr_drop_order.rs +++ b/compiler/rustc_lint/src/tail_expr_drop_order.rs @@ -14,15 +14,14 @@ use rustc_span::edition::Edition; use crate::{LateContext, LateLintPass}; declare_lint! { - /// The `tail_expr_drop_order` lint looks for those values generated at the tail expression location, that of type - /// with a significant `Drop` implementation, such as locks. - /// In case there are also local variables of type with significant `Drop` implementation as well, - /// this lint warns you of a potential transposition in the drop order. - /// Your discretion on the new drop order introduced by Edition 2024 is required. + /// The `tail_expr_drop_order` lint looks for those values generated at the tail expression location, + /// that runs a custom `Drop` destructor. + /// Some of them may be dropped earlier in Edition 2024 that they used to in Edition 2021 and prior. + /// This lint detects those cases and provides you information on those values and their custom destructor implementations. + /// Your discretion on this information is required. /// /// ### Example - /// ```rust,edition2024 - /// #![feature(shorter_tail_lifetimes)] + /// ```rust,edition2021 /// #![warn(tail_expr_drop_order)] /// struct Droppy(i32); /// impl Droppy { @@ -37,12 +36,12 @@ declare_lint! { /// println!("loud drop {}", self.0); /// } /// } - /// fn edition_2024() -> i32 { + /// fn edition_2021() -> i32 { /// let another_droppy = Droppy(0); /// Droppy(1).get() /// } /// fn main() { - /// edition_2024(); + /// edition_2021(); /// } /// ``` /// @@ -137,7 +136,7 @@ impl<'tcx> LateLintPass<'tcx> for TailExprDropOrder { _: Span, def_id: rustc_span::def_id::LocalDefId, ) { - if cx.tcx.sess.at_least_rust_2024() && cx.tcx.features().shorter_tail_lifetimes { + if !body.value.span.edition().at_least_rust_2024() { Self::check_fn_or_closure(cx, fn_kind, body, def_id); } } @@ -185,8 +184,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LintVisitor<'a, 'tcx> { impl<'a, 'tcx> LintVisitor<'a, 'tcx> { fn check_block_inner(&mut self, block: &Block<'tcx>) { - if !block.span.at_least_rust_2024() { - // We only lint for Edition 2024 onwards + if block.span.at_least_rust_2024() { + // We only lint up to Edition 2021 return; } let Some(tail_expr) = block.expr else { return }; diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 660686f4aa280..63534a3d01745 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -395,7 +395,9 @@ impl<'tcx> GenericPredicates<'tcx> { EarlyBinder::bind(self.predicates).iter_instantiated_copied(tcx, args) } - pub fn instantiate_own_identity(self) -> impl Iterator, Span)> { + pub fn instantiate_own_identity( + self, + ) -> impl Iterator, Span)> + DoubleEndedIterator + ExactSizeIterator { EarlyBinder::bind(self.predicates).iter_identity_copied() } diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index dfc82f705a81b..a7e56b8f589b0 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -1048,8 +1048,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // | +------------|outer_scope cache|--+ | // +------------------------------|middle_scope cache|------+ // - // Now, a new, inner-most scope is added along with a new drop into - // both inner-most and outer-most scopes: + // Now, a new, innermost scope is added along with a new drop into + // both innermost and outermost scopes: // // +------------------------------------------------------------+ // | +----------------------------------+ | @@ -1061,11 +1061,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // +----=----------------|invalid middle_scope cache|-----------+ // // If, when adding `drop(new)` we do not invalidate the cached blocks for both - // outer_scope and middle_scope, then, when building drops for the inner (right-most) + // outer_scope and middle_scope, then, when building drops for the inner (rightmost) // scope, the old, cached blocks, without `drop(new)` will get used, producing the // wrong results. // - // Note that this code iterates scopes from the inner-most to the outer-most, + // Note that this code iterates scopes from the innermost to the outermost, // invalidating caches of each scope visited. This way bare minimum of the // caches gets invalidated. i.e., if a new drop is added into the middle scope, the // cache of outer scope stays intact. diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index faee40faa3f55..d0f62bd82d17d 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -1177,7 +1177,7 @@ struct PlaceInfo<'tcx> { /// The projection used to go from parent to this node (only None for root). proj_elem: Option, - /// The left-most child. + /// The leftmost child. first_child: Option, /// Index of the sibling to the right of this node. diff --git a/compiler/rustc_parse/src/lexer/diagnostics.rs b/compiler/rustc_parse/src/lexer/diagnostics.rs index 41108c91f2ebe..e1f19beb53aee 100644 --- a/compiler/rustc_parse/src/lexer/diagnostics.rs +++ b/compiler/rustc_parse/src/lexer/diagnostics.rs @@ -85,7 +85,7 @@ pub(super) fn report_suspicious_mismatch_block( } } - // Find the inner-most span candidate for final report + // Find the innermost span candidate for final report let candidate_span = matched_spans.into_iter().rev().find(|&(_, same_ident)| !same_ident).map(|(span, _)| span); diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index f20beb797500e..c06a578d8ec70 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -496,8 +496,8 @@ where /// Similar to [`instantiate_identity`](EarlyBinder::instantiate_identity), /// but on an iterator of values that deref to a `TypeFoldable`. - pub fn iter_identity_copied(self) -> impl Iterator::Target> { - self.value.into_iter().map(|v| *v) + pub fn iter_identity_copied(self) -> IterIdentityCopied { + IterIdentityCopied { it: self.value.into_iter() } } } @@ -546,6 +546,44 @@ where { } +pub struct IterIdentityCopied { + it: Iter::IntoIter, +} + +impl Iterator for IterIdentityCopied +where + Iter::Item: Deref, + ::Target: Copy, +{ + type Item = ::Target; + + fn next(&mut self) -> Option { + self.it.next().map(|i| *i) + } + + fn size_hint(&self) -> (usize, Option) { + self.it.size_hint() + } +} + +impl DoubleEndedIterator for IterIdentityCopied +where + Iter::IntoIter: DoubleEndedIterator, + Iter::Item: Deref, + ::Target: Copy, +{ + fn next_back(&mut self) -> Option { + self.it.next_back().map(|i| *i) + } +} + +impl ExactSizeIterator for IterIdentityCopied +where + Iter::IntoIter: ExactSizeIterator, + Iter::Item: Deref, + ::Target: Copy, +{ +} pub struct EarlyBinderIter { t: T, _tcx: PhantomData, diff --git a/config.example.toml b/config.example.toml index 168ac353cff75..a52968e9a414d 100644 --- a/config.example.toml +++ b/config.example.toml @@ -419,6 +419,9 @@ # passed to cargo invocations. #jobs = 0 +# What custom diff tool to use for displaying compiletest tests. +#compiletest-diff-tool = + # ============================================================================= # General install configuration options # ============================================================================= diff --git a/library/alloc/src/collections/btree/append.rs b/library/alloc/src/collections/btree/append.rs index 47372938fbeda..d137d2721ee4f 100644 --- a/library/alloc/src/collections/btree/append.rs +++ b/library/alloc/src/collections/btree/append.rs @@ -79,7 +79,7 @@ impl Root { } open_node.push(key, value, right_tree); - // Go down to the right-most leaf again. + // Go down to the rightmost leaf again. cur_node = open_node.forget_type().last_leaf_edge().into_node(); } diff --git a/library/alloc/src/collections/btree/fix.rs b/library/alloc/src/collections/btree/fix.rs index 95fb52b7f77b3..09edea3555ad5 100644 --- a/library/alloc/src/collections/btree/fix.rs +++ b/library/alloc/src/collections/btree/fix.rs @@ -102,7 +102,7 @@ impl Root { pub fn fix_right_border_of_plentiful(&mut self) { let mut cur_node = self.borrow_mut(); while let Internal(internal) = cur_node.force() { - // Check if right-most child is underfull. + // Check if rightmost child is underfull. let mut last_kv = internal.last_kv().consider_for_balancing(); debug_assert!(last_kv.left_child_len() >= MIN_LEN * 2); let right_child_len = last_kv.right_child_len(); diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 5c513d34fc9da..2a853ef421629 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -1521,7 +1521,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { right_node.val_area_mut(..count - 1), ); - // Move the left-most stolen pair to the parent. + // Move the leftmost stolen pair to the parent. let k = left_node.key_area_mut(new_left_len).assume_init_read(); let v = left_node.val_area_mut(new_left_len).assume_init_read(); let (k, v) = self.parent.replace_kv(k, v); @@ -1570,7 +1570,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { // Move leaf data. { - // Move the right-most stolen pair to the parent. + // Move the rightmost stolen pair to the parent. let k = right_node.key_area_mut(count - 1).assume_init_read(); let v = right_node.val_area_mut(count - 1).assume_init_read(); let (k, v) = self.parent.replace_kv(k, v); diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index 6d30f350337aa..2a0ef0189d165 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -71,7 +71,7 @@ pub use self::{ /// this can be useful for specializing [`FromIterator`] implementations or recovering the /// remaining elements after an iterator has been partially exhausted. /// -/// Note that implementations do not necessarily have to provide access to the inner-most +/// Note that implementations do not necessarily have to provide access to the innermost /// source of a pipeline. A stateful intermediate adapter might eagerly evaluate a part /// of the pipeline and expose its internal storage as source. /// diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 04909cd792147..d7ae0299dd696 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -1092,9 +1092,6 @@ def check_vendored_status(self): if not os.path.exists(cargo_dir): eprint('ERROR: vendoring required, but .cargo/config does not exist.') raise Exception("{} not found".format(cargo_dir)) - else: - if os.path.exists(cargo_dir): - shutil.rmtree(cargo_dir) def parse_args(args): """Parse the command line arguments that the python script needs.""" diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 27acaff82554c..2ad1b39a87c83 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1836,6 +1836,9 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the if builder.config.cmd.only_modified() { cmd.arg("--only-modified"); } + if let Some(compiletest_diff_tool) = &builder.config.compiletest_diff_tool { + cmd.arg("--compiletest-diff-tool").arg(compiletest_diff_tool); + } let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] }; flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests)); diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 50f71e167db9f..bb837eb81379a 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -1,8 +1,6 @@ use std::path::PathBuf; use std::{env, fs}; -use build_helper::git::get_closest_merge_commit; - use crate::core::build_steps::compile; use crate::core::build_steps::toolstate::ToolState; use crate::core::builder; @@ -10,7 +8,7 @@ use crate::core::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, use crate::core::config::TargetSelection; use crate::utils::channel::GitInfo; use crate::utils::exec::{BootstrapCommand, command}; -use crate::utils::helpers::{add_dylib_path, exe, git, t}; +use crate::utils::helpers::{add_dylib_path, exe, t}; use crate::{Compiler, Kind, Mode, gha}; #[derive(Debug, Clone, Hash, PartialEq, Eq)] @@ -596,28 +594,11 @@ impl Step for Rustdoc { && target_compiler.stage > 0 && builder.rust_info().is_managed_git_subrepository() { - let commit = get_closest_merge_commit( - Some(&builder.config.src), - &builder.config.git_config(), - &[], - ) - .unwrap(); - - let librustdoc_src = builder.config.src.join("src/librustdoc"); - let rustdoc_src = builder.config.src.join("src/tools/rustdoc"); - - // FIXME: The change detection logic here is quite similar to `Config::download_ci_rustc_commit`. - // It would be better to unify them. - let has_changes = !git(Some(&builder.config.src)) - .allow_failure() - .run_always() - .args(["diff-index", "--quiet", &commit]) - .arg("--") - .arg(librustdoc_src) - .arg(rustdoc_src) - .run(builder); - - if !has_changes { + let files_to_track = &["src/librustdoc", "src/tools/rustdoc"]; + + // Check if unchanged + if builder.config.last_modified_commit(files_to_track, "download-rustc", true).is_some() + { let precompiled_rustdoc = builder .config .ci_rustc_dir() diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index aeb81b146382e..444c97a2048e3 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -368,6 +368,9 @@ pub struct Config { /// The paths to work with. For example: with `./x check foo bar` we get /// `paths=["foo", "bar"]`. pub paths: Vec, + + /// Command for visual diff display, e.g. `diff-tool --color=always`. + pub compiletest_diff_tool: Option, } #[derive(Clone, Debug, Default)] @@ -892,6 +895,7 @@ define_config! { android_ndk: Option = "android-ndk", optimized_compiler_builtins: Option = "optimized-compiler-builtins", jobs: Option = "jobs", + compiletest_diff_tool: Option = "compiletest-diff-tool", } } @@ -1512,6 +1516,7 @@ impl Config { android_ndk, optimized_compiler_builtins, jobs, + compiletest_diff_tool, } = toml.build.unwrap_or_default(); config.jobs = Some(threads_from_config(flags.jobs.unwrap_or(jobs.unwrap_or(0)))); @@ -2158,6 +2163,7 @@ impl Config { config.rust_debuginfo_level_tests = debuginfo_level_tests.unwrap_or(DebuginfoLevel::None); config.optimized_compiler_builtins = optimized_compiler_builtins.unwrap_or(config.channel != "dev"); + config.compiletest_diff_tool = compiletest_diff_tool; let download_rustc = config.download_rustc_commit.is_some(); // See https://github.com/rust-lang/compiler-team/issues/326 @@ -2754,25 +2760,25 @@ impl Config { } }; - let files_to_track = &[ - self.src.join("compiler"), - self.src.join("library"), - self.src.join("src/version"), - self.src.join("src/stage0"), - self.src.join("src/ci/channel"), - ]; + let files_to_track = + &["compiler", "library", "src/version", "src/stage0", "src/ci/channel"]; // Look for a version to compare to based on the current commit. // Only commits merged by bors will have CI artifacts. - let commit = - get_closest_merge_commit(Some(&self.src), &self.git_config(), files_to_track).unwrap(); - if commit.is_empty() { - println!("ERROR: could not find commit hash for downloading rustc"); - println!("HELP: maybe your repository history is too shallow?"); - println!("HELP: consider disabling `download-rustc`"); - println!("HELP: or fetch enough history to include one upstream commit"); - crate::exit!(1); - } + let commit = match self.last_modified_commit(files_to_track, "download-rustc", if_unchanged) + { + Some(commit) => commit, + None => { + if if_unchanged { + return None; + } + println!("ERROR: could not find commit hash for downloading rustc"); + println!("HELP: maybe your repository history is too shallow?"); + println!("HELP: consider disabling `download-rustc`"); + println!("HELP: or fetch enough history to include one upstream commit"); + crate::exit!(1); + } + }; if CiEnv::is_ci() && { let head_sha = @@ -2787,31 +2793,7 @@ impl Config { return None; } - // Warn if there were changes to the compiler or standard library since the ancestor commit. - let has_changes = !t!(helpers::git(Some(&self.src)) - .args(["diff-index", "--quiet", &commit]) - .arg("--") - .args(files_to_track) - .as_command_mut() - .status()) - .success(); - if has_changes { - if if_unchanged { - if self.is_verbose() { - println!( - "WARNING: saw changes to compiler/ or library/ since {commit}; \ - ignoring `download-rustc`" - ); - } - return None; - } - println!( - "WARNING: `download-rustc` is enabled, but there are changes to \ - compiler/ or library/" - ); - } - - Some(commit.to_string()) + Some(commit) } fn parse_download_ci_llvm( diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 9169bc90a45dc..fac24572a878c 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -280,4 +280,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Info, summary: "Allow setting `--jobs` in config.toml with `build.jobs`.", }, + ChangeInfo { + change_id: 131181, + severity: ChangeSeverity::Info, + summary: "New option `build.compiletest-diff-tool` that adds support for a custom differ for compiletest", + }, ]; diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index 27dbfc6040ce0..f07515f7784f4 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -2,7 +2,7 @@ set -euo pipefail -LINUX_VERSION=v6.12-rc2 +LINUX_VERSION=28e848386b92645f93b9f2fdba5882c3ca7fb3e2 # Build rustc, rustdoc, cargo, clippy-driver and rustfmt ../x.py build --stage 2 library rustdoc clippy rustfmt diff --git a/src/doc/rustc/src/symbol-mangling/v0.md b/src/doc/rustc/src/symbol-mangling/v0.md index 6329e878c5c85..109942518fc93 100644 --- a/src/doc/rustc/src/symbol-mangling/v0.md +++ b/src/doc/rustc/src/symbol-mangling/v0.md @@ -1208,7 +1208,7 @@ The compiler has some latitude in how an entity is encoded as long as the symbol * Named functions, methods, and statics shall be represented by a *[path]* production. -* Paths should be rooted at the inner-most entity that can act as a path root. +* Paths should be rooted at the innermost entity that can act as a path root. Roots can be crate-ids, inherent impls, trait impls, and (for items within default methods) trait definitions. * The compiler is free to choose disambiguation indices and namespace tags from diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 12b6346005697..c82f7e9aaf927 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -112,7 +112,7 @@ pub(crate) fn write_shared( md_opts.output = cx.dst.clone(); md_opts.external_html = cx.shared.layout.external_html.clone(); try_err!( - crate::markdown::render(&index_page, md_opts, cx.shared.edition()), + crate::markdown::render_and_write(&index_page, md_opts, cx.shared.edition()), &index_page ); } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 10fc0ea999015..cb9b3985bf67f 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -817,7 +817,7 @@ fn main_args( return wrap_return( dcx, interface::run_compiler(config, |_compiler| { - markdown::render(&md_input, render_options, edition) + markdown::render_and_write(&md_input, render_options, edition) }), ); } diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 978f96f38bedf..76eac084907d7 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -1,3 +1,13 @@ +//! Standalone markdown rendering. +//! +//! For the (much more common) case of rendering markdown in doc-comments, see +//! [crate::html::markdown]. +//! +//! This is used when [rendering a markdown file to an html file][docs], without processing +//! rust source code. +//! +//! [docs]: https://doc.rust-lang.org/stable/rustdoc/#using-standalone-markdown-files + use std::fmt::Write as _; use std::fs::{File, create_dir_all, read_to_string}; use std::io::prelude::*; @@ -33,7 +43,7 @@ fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) { /// (e.g., output = "bar" => "bar/foo.html"). /// /// Requires session globals to be available, for symbol interning. -pub(crate) fn render>( +pub(crate) fn render_and_write>( input: P, options: RenderOptions, edition: Edition, diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index ff059940f7ccd..5070f016d3c62 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -387,6 +387,9 @@ pub struct Config { /// True if the profiler runtime is enabled for this target. /// Used by the "needs-profiler-runtime" directive in test files. pub profiler_runtime: bool, + + /// Command for visual diff display, e.g. `diff-tool --color=always`. + pub diff_command: Option, } impl Config { diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 7d6ede9bcdac5..0f514db42bf9f 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -175,6 +175,12 @@ pub fn parse_config(args: Vec) -> Config { "git-merge-commit-email", "email address used for finding merge commits", "EMAIL", + ) + .optopt( + "", + "compiletest-diff-tool", + "What custom diff tool to use for displaying compiletest tests.", + "COMMAND", ); let (argv0, args_) = args.split_first().unwrap(); @@ -364,6 +370,7 @@ pub fn parse_config(args: Vec) -> Config { git_merge_commit_email: matches.opt_str("git-merge-commit-email").unwrap(), profiler_runtime: matches.opt_present("profiler-runtime"), + diff_command: matches.opt_str("compiletest-diff-tool"), } } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 36c5106ddad03..7db37af60d2c5 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2459,7 +2459,7 @@ impl<'test> TestCx<'test> { } } - fn compare_output(&self, kind: &str, actual: &str, expected: &str) -> usize { + fn compare_output(&self, stream: &str, actual: &str, expected: &str) -> usize { let are_different = match (self.force_color_svg(), expected.find('\n'), actual.find('\n')) { // FIXME: We ignore the first line of SVG files // because the width parameter is non-deterministic. @@ -2499,56 +2499,66 @@ impl<'test> TestCx<'test> { (expected, actual) }; + // Write the actual output to a file in build/ + let test_name = self.config.compare_mode.as_ref().map_or("", |m| m.to_str()); + let actual_path = self + .output_base_name() + .with_extra_extension(self.revision.unwrap_or("")) + .with_extra_extension(test_name) + .with_extra_extension(stream); + + if let Err(err) = fs::write(&actual_path, &actual) { + self.fatal(&format!("failed to write {stream} to `{actual_path:?}`: {err}",)); + } + println!("Saved the actual {stream} to {actual_path:?}"); + + let expected_path = + expected_output_path(self.testpaths, self.revision, &self.config.compare_mode, stream); + if !self.config.bless { if expected.is_empty() { - println!("normalized {}:\n{}\n", kind, actual); + println!("normalized {}:\n{}\n", stream, actual); } else { - println!("diff of {}:\n", kind); - print!("{}", write_diff(expected, actual, 3)); + println!("diff of {stream}:\n"); + if let Some(diff_command) = self.config.diff_command.as_deref() { + let mut args = diff_command.split_whitespace(); + let name = args.next().unwrap(); + match Command::new(name) + .args(args) + .args([&expected_path, &actual_path]) + .output() + { + Err(err) => { + self.fatal(&format!( + "failed to call custom diff command `{diff_command}`: {err}" + )); + } + Ok(output) => { + let output = String::from_utf8_lossy(&output.stdout); + print!("{output}"); + } + } + } else { + print!("{}", write_diff(expected, actual, 3)); + } } - } - - let mode = self.config.compare_mode.as_ref().map_or("", |m| m.to_str()); - let output_file = self - .output_base_name() - .with_extra_extension(self.revision.unwrap_or("")) - .with_extra_extension(mode) - .with_extra_extension(kind); - - let mut files = vec![output_file]; - if self.config.bless { + } else { // Delete non-revision .stderr/.stdout file if revisions are used. // Without this, we'd just generate the new files and leave the old files around. if self.revision.is_some() { let old = - expected_output_path(self.testpaths, None, &self.config.compare_mode, kind); + expected_output_path(self.testpaths, None, &self.config.compare_mode, stream); self.delete_file(&old); } - files.push(expected_output_path( - self.testpaths, - self.revision, - &self.config.compare_mode, - kind, - )); - } - for output_file in &files { - if actual.is_empty() { - self.delete_file(output_file); - } else if let Err(err) = fs::write(&output_file, &actual) { - self.fatal(&format!( - "failed to write {} to `{}`: {}", - kind, - output_file.display(), - err, - )); + if let Err(err) = fs::write(&expected_path, &actual) { + self.fatal(&format!("failed to write {stream} to `{expected_path:?}`: {err}")); } + println!("Blessing the {stream} of {test_name} in {expected_path:?}"); } - println!("\nThe actual {0} differed from the expected {0}.", kind); - for output_file in files { - println!("Actual {} saved to {}", kind, output_file.display()); - } + println!("\nThe actual {0} differed from the expected {0}.", stream); + if self.config.bless { 0 } else { 1 } } diff --git a/tests/ui/drop/drop_order.rs b/tests/ui/drop/drop_order.rs index cf06253800745..29b68d666fc6e 100644 --- a/tests/ui/drop/drop_order.rs +++ b/tests/ui/drop/drop_order.rs @@ -105,6 +105,7 @@ impl DropOrderCollector { () => self.print(10), } + #[cfg(edition2021)] match { match self.option_loud_drop(14) { _ => { @@ -115,6 +116,17 @@ impl DropOrderCollector { } { _ => self.print(12), } + #[cfg(edition2024)] + match { + match self.option_loud_drop(12) { + _ => { + self.print(11); + self.option_loud_drop(14) + } + } + } { + _ => self.print(13), + } match { loop { diff --git a/tests/ui/drop/lint-tail-expr-drop-order-gated.rs b/tests/ui/drop/lint-tail-expr-drop-order-gated.rs index b22e72bcfad22..fde542c756f2e 100644 --- a/tests/ui/drop/lint-tail-expr-drop-order-gated.rs +++ b/tests/ui/drop/lint-tail-expr-drop-order-gated.rs @@ -1,15 +1,11 @@ -// This test ensures that `tail_expr_drop_order` does not activate in case Edition 2024 is not used -// or the feature gate `shorter_tail_lifetimes` is disabled. +// This test is to demonstrate that the lint is gated behind Edition and +// is triggered only for Edition 2021 and before. -//@ revisions: neither no_feature_gate edition_less_than_2024 //@ check-pass -//@ [neither] edition: 2021 -//@ [no_feature_gate] compile-flags: -Z unstable-options -//@ [no_feature_gate] edition: 2024 -//@ [edition_less_than_2024] edition: 2021 +//@ edition: 2024 +//@ compile-flags: -Z unstable-options #![deny(tail_expr_drop_order)] -#![cfg_attr(edition_less_than_2024, feature(shorter_tail_lifetimes))] struct LoudDropper; impl Drop for LoudDropper { diff --git a/tests/ui/drop/lint-tail-expr-drop-order.rs b/tests/ui/drop/lint-tail-expr-drop-order.rs index 0aa0ef026101a..d61abae518707 100644 --- a/tests/ui/drop/lint-tail-expr-drop-order.rs +++ b/tests/ui/drop/lint-tail-expr-drop-order.rs @@ -1,12 +1,10 @@ -//@ compile-flags: -Z unstable-options -//@ edition: 2024 +//@ edition: 2021 // Edition 2024 lint for change in drop order at tail expression // This lint is to capture potential change in program semantics // due to implementation of RFC 3606 #![deny(tail_expr_drop_order)] -#![feature(shorter_tail_lifetimes)] struct LoudDropper; impl Drop for LoudDropper { diff --git a/tests/ui/drop/lint-tail-expr-drop-order.stderr b/tests/ui/drop/lint-tail-expr-drop-order.stderr index 630f0a80f092b..6775c4ce6d15a 100644 --- a/tests/ui/drop/lint-tail-expr-drop-order.stderr +++ b/tests/ui/drop/lint-tail-expr-drop-order.stderr @@ -1,5 +1,5 @@ error: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021 - --> $DIR/lint-tail-expr-drop-order.rs:29:15 + --> $DIR/lint-tail-expr-drop-order.rs:27:15 | LL | let x = LoudDropper; | - these values have significant drop implementation and will observe changes in drop order under Edition 2024 @@ -10,13 +10,13 @@ LL | x.get() + LoudDropper.get() = warning: this changes meaning in Rust 2024 = note: for more information, see issue #123739 note: the lint level is defined here - --> $DIR/lint-tail-expr-drop-order.rs:8:9 + --> $DIR/lint-tail-expr-drop-order.rs:7:9 | LL | #![deny(tail_expr_drop_order)] | ^^^^^^^^^^^^^^^^^^^^ error: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021 - --> $DIR/lint-tail-expr-drop-order.rs:36:23 + --> $DIR/lint-tail-expr-drop-order.rs:34:23 | LL | let x = LoudDropper; | - these values have significant drop implementation and will observe changes in drop order under Edition 2024 @@ -27,7 +27,7 @@ LL | move || x.get() + LoudDropper.get() = note: for more information, see issue #123739 error: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021 - --> $DIR/lint-tail-expr-drop-order.rs:65:19 + --> $DIR/lint-tail-expr-drop-order.rs:63:19 | LL | let x = LoudDropper; | - these values have significant drop implementation and will observe changes in drop order under Edition 2024 diff --git a/tests/ui/drop/tail-expr-drop-order-negative.edition2024.stderr b/tests/ui/drop/tail-expr-drop-order-negative.edition2024.stderr index 75fc34e409b54..bcce796570e29 100644 --- a/tests/ui/drop/tail-expr-drop-order-negative.edition2024.stderr +++ b/tests/ui/drop/tail-expr-drop-order-negative.edition2024.stderr @@ -1,5 +1,5 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/tail-expr-drop-order-negative.rs:11:15 + --> $DIR/tail-expr-drop-order-negative.rs:9:15 | LL | x.replace(std::cell::RefCell::new(123).borrow()).is_some() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement diff --git a/tests/ui/drop/tail-expr-drop-order-negative.rs b/tests/ui/drop/tail-expr-drop-order-negative.rs index c570b3a1ee235..5ad04d0a67ef6 100644 --- a/tests/ui/drop/tail-expr-drop-order-negative.rs +++ b/tests/ui/drop/tail-expr-drop-order-negative.rs @@ -3,8 +3,6 @@ //@ [edition2024] edition: 2024 //@ [edition2021] check-pass -#![feature(shorter_tail_lifetimes)] - fn why_would_you_do_this() -> bool { let mut x = None; // Make a temporary `RefCell` and put a `Ref` that borrows it in `x`. diff --git a/tests/ui/drop/tail-expr-drop-order.rs b/tests/ui/drop/tail-expr-drop-order.rs index 5d87f980b1563..80968b823f9a7 100644 --- a/tests/ui/drop/tail-expr-drop-order.rs +++ b/tests/ui/drop/tail-expr-drop-order.rs @@ -4,7 +4,6 @@ //@ edition: 2024 //@ run-pass -#![feature(shorter_tail_lifetimes)] #![allow(unused_imports)] #![allow(dead_code)] #![allow(unused_variables)] diff --git a/tests/ui/lifetimes/refcell-in-tail-expr.edition2021.stderr b/tests/ui/lifetimes/refcell-in-tail-expr.edition2021.stderr index 858be42d54094..157a1c5e09b07 100644 --- a/tests/ui/lifetimes/refcell-in-tail-expr.edition2021.stderr +++ b/tests/ui/lifetimes/refcell-in-tail-expr.edition2021.stderr @@ -1,5 +1,5 @@ error[E0597]: `cell` does not live long enough - --> $DIR/refcell-in-tail-expr.rs:12:27 + --> $DIR/refcell-in-tail-expr.rs:10:27 | LL | let cell = std::cell::RefCell::new(0u8); | ---- binding `cell` declared here diff --git a/tests/ui/lifetimes/refcell-in-tail-expr.rs b/tests/ui/lifetimes/refcell-in-tail-expr.rs index b1814c1e32713..595e951f3731b 100644 --- a/tests/ui/lifetimes/refcell-in-tail-expr.rs +++ b/tests/ui/lifetimes/refcell-in-tail-expr.rs @@ -4,8 +4,6 @@ //@ [edition2024] compile-flags: -Zunstable-options //@ [edition2024] check-pass -#![cfg_attr(edition2024, feature(shorter_tail_lifetimes))] - fn main() { let cell = std::cell::RefCell::new(0u8); diff --git a/tests/ui/lifetimes/shorter-tail-expr-lifetime.edition2021.stderr b/tests/ui/lifetimes/shorter-tail-expr-lifetime.edition2021.stderr index ad28ae2f80d66..3c074c5c3a2cb 100644 --- a/tests/ui/lifetimes/shorter-tail-expr-lifetime.edition2021.stderr +++ b/tests/ui/lifetimes/shorter-tail-expr-lifetime.edition2021.stderr @@ -1,5 +1,5 @@ error[E0597]: `c` does not live long enough - --> $DIR/shorter-tail-expr-lifetime.rs:10:5 + --> $DIR/shorter-tail-expr-lifetime.rs:8:5 | LL | let c = std::cell::RefCell::new(".."); | - binding `c` declared here diff --git a/tests/ui/lifetimes/shorter-tail-expr-lifetime.rs b/tests/ui/lifetimes/shorter-tail-expr-lifetime.rs index 0392b6c6d9ada..4195a8b6c32bd 100644 --- a/tests/ui/lifetimes/shorter-tail-expr-lifetime.rs +++ b/tests/ui/lifetimes/shorter-tail-expr-lifetime.rs @@ -3,8 +3,6 @@ //@ [edition2024] edition: 2024 //@ [edition2024] run-pass -#![cfg_attr(edition2024, feature(shorter_tail_lifetimes))] - fn f() -> usize { let c = std::cell::RefCell::new(".."); c.borrow().len() //[edition2021]~ ERROR: `c` does not live long enough diff --git a/tests/ui/lifetimes/tail-expr-in-nested-expr.rs b/tests/ui/lifetimes/tail-expr-in-nested-expr.rs index a8989f22f4b5b..2ac97aff2b098 100644 --- a/tests/ui/lifetimes/tail-expr-in-nested-expr.rs +++ b/tests/ui/lifetimes/tail-expr-in-nested-expr.rs @@ -1,8 +1,6 @@ //@ edition: 2024 //@ compile-flags: -Zunstable-options -#![feature(shorter_tail_lifetimes)] - fn main() { let _ = { String::new().as_str() }.len(); //~^ ERROR temporary value dropped while borrowed diff --git a/tests/ui/lifetimes/tail-expr-in-nested-expr.stderr b/tests/ui/lifetimes/tail-expr-in-nested-expr.stderr index f699d184bdb1d..96e88eaca9225 100644 --- a/tests/ui/lifetimes/tail-expr-in-nested-expr.stderr +++ b/tests/ui/lifetimes/tail-expr-in-nested-expr.stderr @@ -1,5 +1,5 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/tail-expr-in-nested-expr.rs:7:15 + --> $DIR/tail-expr-in-nested-expr.rs:5:15 | LL | let _ = { String::new().as_str() }.len(); | ^^^^^^^^^^^^^--------- diff --git a/tests/ui/lifetimes/tail-expr-lock-poisoning.rs b/tests/ui/lifetimes/tail-expr-lock-poisoning.rs index cdfd35304b44e..ec74596a08da4 100644 --- a/tests/ui/lifetimes/tail-expr-lock-poisoning.rs +++ b/tests/ui/lifetimes/tail-expr-lock-poisoning.rs @@ -4,7 +4,6 @@ //@ [edition2024] edition: 2024 //@ run-pass //@ needs-unwind -#![cfg_attr(edition2024, feature(shorter_tail_lifetimes))] use std::sync::Mutex; diff --git a/tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs b/tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs index 131d4166de04a..8ca453273cd84 100644 --- a/tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs +++ b/tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs @@ -6,9 +6,9 @@ fn main() { macro_rules! one_nested_count_and_len { ( $( [ $( $l:literal ),* ] ),* ) => { [ - // outer-most repetition + // outermost repetition $( - // inner-most repetition + // innermost repetition $( ${ignore($l)} ${index()}, ${len()}, )* @@ -23,34 +23,34 @@ fn main() { [ // # ["foo"] - // ## inner-most repetition (first iteration) + // ## innermost repetition (first iteration) // - // `index` is 0 because this is the first inner-most iteration. - // `len` is 1 because there is only one inner-most repetition, "foo". + // `index` is 0 because this is the first innermost iteration. + // `len` is 1 because there is only one innermost repetition, "foo". 0, 1, - // ## outer-most repetition (first iteration) + // ## outermost repetition (first iteration) // // `count` is 1 because of "foo", i,e, `$l` has only one repetition, - // `index` is 0 because this is the first outer-most iteration. - // `len` is 2 because there are 2 outer-most repetitions, ["foo"] and ["bar", "baz"] + // `index` is 0 because this is the first outermost iteration. + // `len` is 2 because there are 2 outermost repetitions, ["foo"] and ["bar", "baz"] 1, 0, 2, // # ["bar", "baz"] - // ## inner-most repetition (first iteration) + // ## innermost repetition (first iteration) // - // `index` is 0 because this is the first inner-most iteration + // `index` is 0 because this is the first innermost iteration // `len` is 2 because there are repetitions, "bar" and "baz" 0, 2, - // ## inner-most repetition (second iteration) + // ## innermost repetition (second iteration) // - // `index` is 1 because this is the second inner-most iteration + // `index` is 1 because this is the second innermost iteration // `len` is 2 because there are repetitions, "bar" and "baz" 1, 2, - // ## outer-most repetition (second iteration) + // ## outermost repetition (second iteration) // // `count` is 2 because of "bar" and "baz", i,e, `$l` has two repetitions, - // `index` is 1 because this is the second outer-most iteration - // `len` is 2 because there are 2 outer-most repetitions, ["foo"] and ["bar", "baz"] + // `index` is 1 because this is the second outermost iteration + // `len` is 2 because there are 2 outermost repetitions, ["foo"] and ["bar", "baz"] 2, 1, 2, // # last count @@ -61,7 +61,7 @@ fn main() { // Based on the above explanation, the following macros should be straightforward - // Grouped from the outer-most to the inner-most + // Grouped from the outermost to the innermost macro_rules! three_nested_count { ( $( { $( [ $( ( $( $i:ident )* ) )* ] )* } )* ) => { &[ @@ -156,7 +156,7 @@ fn main() { ][..] ); - // Grouped from the outer-most to the inner-most + // Grouped from the outermost to the innermost macro_rules! three_nested_len { ( $( { $( [ $( ( $( $i:ident )* ) )* ] )* } )* ) => { &[ diff --git a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs index 1eda5f5bb6bc3..78cede92526ba 100644 --- a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs +++ b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs @@ -10,12 +10,12 @@ macro_rules! curly__no_rhs_dollar__round { macro_rules! curly__no_rhs_dollar__no_round { ( $i:ident ) => { ${ count($i) } }; - //~^ ERROR `count` can not be placed inside the inner-most repetition + //~^ ERROR `count` can not be placed inside the innermost repetition } macro_rules! curly__rhs_dollar__no_round { ( $i:ident ) => { ${ count($i) } }; - //~^ ERROR `count` can not be placed inside the inner-most repetition + //~^ ERROR `count` can not be placed inside the innermost repetition } #[rustfmt::skip] // autoformatters can break a few of the error traces diff --git a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr index 2c44ad2e0a4ad..ce7694ecb1da3 100644 --- a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr +++ b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr @@ -196,13 +196,13 @@ error: expected identifier or string literal LL | ( $( $i:ident ),* ) => { ${ {} } }; | ^^ -error: `count` can not be placed inside the inner-most repetition +error: `count` can not be placed inside the innermost repetition --> $DIR/syntax-errors.rs:12:24 | LL | ( $i:ident ) => { ${ count($i) } }; | ^^^^^^^^^^^^^ -error: `count` can not be placed inside the inner-most repetition +error: `count` can not be placed inside the innermost repetition --> $DIR/syntax-errors.rs:17:24 | LL | ( $i:ident ) => { ${ count($i) } };