From b468bfb36183bd1e688c16687139bcfa886efff6 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 4 Jul 2023 10:06:39 +0200 Subject: [PATCH 01/22] -Ztrait-solver=next: stop depending on old solver --- compiler/rustc_infer/src/infer/projection.rs | 37 ++++------- .../src/solve/normalize.rs | 2 + .../src/traits/coherence.rs | 22 +++++-- .../src/traits/project.rs | 2 + .../src/traits/query/evaluate_obligation.rs | 1 + .../query/type_op/implied_outlives_bounds.rs | 28 +++++--- .../src/traits/select/candidate_assembly.rs | 4 +- .../src/traits/select/mod.rs | 65 ++++++------------- .../rustc_trait_selection/src/traits/wf.rs | 5 ++ 9 files changed, 82 insertions(+), 84 deletions(-) diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs index 7545553318136..38e74e538687e 100644 --- a/compiler/rustc_infer/src/infer/projection.rs +++ b/compiler/rustc_infer/src/infer/projection.rs @@ -21,29 +21,18 @@ impl<'tcx> InferCtxt<'tcx> { recursion_depth: usize, obligations: &mut Vec>, ) -> Ty<'tcx> { - if self.next_trait_solver() { - // FIXME(-Ztrait-solver=next): Instead of branching here, - // completely change the normalization routine with the new solver. - // - // The new solver correctly handles projection equality so this hack - // is not necessary. if re-enabled it should emit `PredicateKind::AliasRelate` - // not `PredicateKind::Clause(ClauseKind::Projection(..))` as in the new solver - // `Projection` is used as `normalizes-to` which will fail for `::Assoc eq ?0`. - return projection_ty.to_ty(self.tcx); - } else { - let def_id = projection_ty.def_id; - let ty_var = self.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::NormalizeProjectionType, - span: self.tcx.def_span(def_id), - }); - let projection = - ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Projection( - ty::ProjectionPredicate { projection_ty, term: ty_var.into() }, - ))); - let obligation = - Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection); - obligations.push(obligation); - ty_var - } + debug_assert!(!self.next_trait_solver()); + let def_id = projection_ty.def_id; + let ty_var = self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::NormalizeProjectionType, + span: self.tcx.def_span(def_id), + }); + let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Projection( + ty::ProjectionPredicate { projection_ty, term: ty_var.into() }, + ))); + let obligation = + Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection); + obligations.push(obligation); + ty_var } } diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index d2eed10950f1c..6b468b81f7a73 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -159,6 +159,7 @@ impl<'tcx> FallibleTypeFolder> for NormalizationFolder<'_, 'tcx> { fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result, Self::Error> { let reveal = self.at.param_env.reveal(); let infcx = self.at.infcx; + debug_assert_eq!(ty, infcx.shallow_resolve(ty)); if !needs_normalization(&ty, reveal) { return Ok(ty); } @@ -192,6 +193,7 @@ impl<'tcx> FallibleTypeFolder> for NormalizationFolder<'_, 'tcx> { fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result, Self::Error> { let reveal = self.at.param_env.reveal(); let infcx = self.at.infcx; + debug_assert_eq!(ct, infcx.shallow_resolve(ct)); if !needs_normalization(&ct, reveal) { return Ok(ct); } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 4cfe2bfcb12b4..1b1285e1b461a 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -30,6 +30,7 @@ use std::fmt::Debug; use std::iter; use std::ops::ControlFlow; +use super::query::evaluate_obligation::InferCtxtExt; use super::NormalizeExt; /// Whether we do the orphan check relative to this crate or @@ -290,6 +291,20 @@ fn impl_intersection_has_impossible_obligation<'cx, 'tcx>( ) -> bool { let infcx = selcx.infcx; + let obligation_guaranteed_to_fail = move |obligation: &PredicateObligation<'tcx>| { + if infcx.next_trait_solver() { + infcx.evaluate_obligation(obligation).map_or(false, |result| !result.may_apply()) + } else { + // We use `evaluate_root_obligation` to correctly track + // intercrate ambiguity clauses. We do not need this in the + // new solver. + selcx.evaluate_root_obligation(obligation).map_or( + false, // Overflow has occurred, and treat the obligation as possibly holding. + |result| !result.may_apply(), + ) + } + }; + let opt_failing_obligation = [&impl1_header.predicates, &impl2_header.predicates] .into_iter() .flatten() @@ -297,12 +312,7 @@ fn impl_intersection_has_impossible_obligation<'cx, 'tcx>( Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, predicate) }) .chain(obligations) - .find(|o| { - selcx.evaluate_root_obligation(o).map_or( - false, // Overflow has occurred, and treat the obligation as possibly holding. - |result| !result.may_apply(), - ) - }); + .find(obligation_guaranteed_to_fail); if let Some(failing_obligation) = opt_failing_obligation { debug!("overlap: obligation unsatisfiable {:?}", failing_obligation); diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 162e51d1fd612..1d9f9e3e365d0 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -447,6 +447,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { depth: usize, obligations: &'a mut Vec>, ) -> AssocTypeNormalizer<'a, 'b, 'tcx> { + debug_assert!(!selcx.infcx.next_trait_solver()); AssocTypeNormalizer { selcx, param_env, @@ -1122,6 +1123,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( obligations: &mut Vec>, ) -> Result>, InProgress> { let infcx = selcx.infcx; + debug_assert!(!selcx.infcx.next_trait_solver()); // Don't use the projection cache in intercrate mode - // the `infcx` may be re-used between intercrate in non-intercrate // mode, which could lead to using incorrect cache results. diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs index e29e1b2591900..a50644bb70920 100644 --- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs +++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs @@ -97,6 +97,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { } }) } else { + assert!(!self.intercrate); let c_pred = self.canonicalize_query_keep_static( param_env.and(obligation.predicate), &mut _orig_values, diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index 83d536c9ca56b..f282474133cf6 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -1,3 +1,4 @@ +use crate::solve; use crate::traits::query::NoSolution; use crate::traits::wf; use crate::traits::ObligationCtxt; @@ -6,6 +7,7 @@ use rustc_infer::infer::canonical::Canonical; use rustc_infer::infer::outlives::components::{push_outlives_components, Component}; use rustc_infer::traits::query::OutlivesBound; use rustc_middle::infer::canonical::CanonicalQueryResponse; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::source_map::DUMMY_SP; @@ -164,19 +166,29 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( // We lazily compute the outlives components as // `select_all_or_error` constrains inference variables. - let implied_bounds = outlives_bounds - .into_iter() - .flat_map(|ty::OutlivesPredicate(a, r_b)| match a.unpack() { - ty::GenericArgKind::Lifetime(r_a) => vec![OutlivesBound::RegionSubRegion(r_b, r_a)], + let mut implied_bounds = Vec::new(); + for ty::OutlivesPredicate(a, r_b) in outlives_bounds { + match a.unpack() { + ty::GenericArgKind::Lifetime(r_a) => { + implied_bounds.push(OutlivesBound::RegionSubRegion(r_b, r_a)) + } ty::GenericArgKind::Type(ty_a) => { - let ty_a = ocx.infcx.resolve_vars_if_possible(ty_a); + let mut ty_a = ocx.infcx.resolve_vars_if_possible(ty_a); + // Need to manually normalize in the new solver as `wf::obligations` does not. + if ocx.infcx.next_trait_solver() { + ty_a = solve::deeply_normalize( + ocx.infcx.at(&ObligationCause::dummy(), param_env), + ty_a, + ) + .map_err(|_errs| NoSolution)?; + } let mut components = smallvec![]; push_outlives_components(tcx, ty_a, &mut components); - implied_bounds_from_components(r_b, components) + implied_bounds.extend(implied_bounds_from_components(r_b, components)) } ty::GenericArgKind::Const(_) => unreachable!(), - }) - .collect(); + } + } Ok(implied_bounds) } 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 412b601c966ff..a032925970578 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -388,7 +388,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// `FnPtr`, when we wanted to report that it doesn't implement `Trait`. #[instrument(level = "trace", skip(self), ret)] fn reject_fn_ptr_impls( - &self, + &mut self, impl_def_id: DefId, obligation: &TraitObligation<'tcx>, impl_self_ty: Ty<'tcx>, @@ -464,7 +464,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) })), ); - if let Ok(r) = self.infcx.evaluate_obligation(&obligation) { + if let Ok(r) = self.evaluate_root_obligation(&obligation) { if !r.may_apply() { return true; } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index c12d92b90124c..74a051236e58f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -34,8 +34,6 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::LateBoundRegionConversionTime; -use rustc_infer::traits::TraitEngine; -use rustc_infer::traits::TraitEngineExt; use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::abstract_const::NotConstEvaluatable; @@ -312,6 +310,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, stack: &TraitObligationStack<'o, 'tcx>, ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { + debug_assert!(!self.infcx.next_trait_solver()); // Watch out for overflow. This intentionally bypasses (and does // not update) the cache. self.check_recursion_limit(&stack.obligation, &stack.obligation)?; @@ -526,21 +525,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Evaluates whether the obligation `obligation` can be satisfied /// and returns an `EvaluationResult`. This is meant for the /// *initial* call. + /// + /// Do not use this directly, use `infcx.evaluate_obligation` instead. pub fn evaluate_root_obligation( &mut self, obligation: &PredicateObligation<'tcx>, ) -> Result { + debug_assert!(!self.infcx.next_trait_solver()); self.evaluation_probe(|this| { let goal = this.infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env)); - let mut result = if this.infcx.next_trait_solver() { - this.evaluate_predicates_recursively_in_new_solver([obligation.clone()])? - } else { - this.evaluate_predicate_recursively( - TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()), - obligation.clone(), - )? - }; + let mut result = this.evaluate_predicate_recursively( + TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()), + obligation.clone(), + )?; // If the predicate has done any inference, then downgrade the // result to ambiguous. if this.infcx.shallow_resolve(goal) != goal { @@ -587,42 +585,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { where I: IntoIterator> + std::fmt::Debug, { - if self.infcx.next_trait_solver() { - self.evaluate_predicates_recursively_in_new_solver(predicates) - } else { - let mut result = EvaluatedToOk; - for mut obligation in predicates { - obligation.set_depth_from_parent(stack.depth()); - let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?; - if let EvaluatedToErr = eval { - // fast-path - EvaluatedToErr is the top of the lattice, - // so we don't need to look on the other predicates. - return Ok(EvaluatedToErr); - } else { - result = cmp::max(result, eval); - } + let mut result = EvaluatedToOk; + for mut obligation in predicates { + obligation.set_depth_from_parent(stack.depth()); + let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?; + if let EvaluatedToErr = eval { + // fast-path - EvaluatedToErr is the top of the lattice, + // so we don't need to look on the other predicates. + return Ok(EvaluatedToErr); + } else { + result = cmp::max(result, eval); } - Ok(result) - } - } - - /// Evaluates the predicates using the new solver when `-Ztrait-solver=next` is enabled - fn evaluate_predicates_recursively_in_new_solver( - &mut self, - predicates: impl IntoIterator>, - ) -> Result { - let mut fulfill_cx = crate::solve::FulfillmentCtxt::new(self.infcx); - fulfill_cx.register_predicate_obligations(self.infcx, predicates); - // True errors - // FIXME(-Ztrait-solver=next): Overflows are reported as ambig here, is that OK? - if !fulfill_cx.select_where_possible(self.infcx).is_empty() { - return Ok(EvaluatedToErr); } - if !fulfill_cx.select_all_or_error(self.infcx).is_empty() { - return Ok(EvaluatedToAmbig); - } - // Regions and opaques are handled in the `evaluation_probe` by looking at the snapshot - Ok(EvaluatedToOk) + Ok(result) } #[instrument( @@ -636,6 +611,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { previous_stack: TraitObligationStackList<'o, 'tcx>, obligation: PredicateObligation<'tcx>, ) -> Result { + debug_assert!(!self.infcx.next_trait_solver()); // `previous_stack` stores a `TraitObligation`, while `obligation` is // a `PredicateObligation`. These are distinct types, so we can't // use any `Option` combinator method that would force them to be @@ -1182,6 +1158,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, stack: &TraitObligationStack<'o, 'tcx>, ) -> Result { + debug_assert!(!self.infcx.next_trait_solver()); // In intercrate mode, whenever any of the generics are unbound, // there can always be an impl. Even if there are no impls in // this crate, perhaps the type would be unified with diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 8bb4288f80de0..b0798ace60dff 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -303,6 +303,11 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } fn normalize(self, infcx: &InferCtxt<'tcx>) -> Vec> { + // Do not normalize `wf` obligations with the new solver. + if infcx.next_trait_solver() { + return self.out; + } + let cause = self.cause(traits::WellFormed(None)); let param_env = self.param_env; let mut obligations = Vec::with_capacity(self.out.len()); From 312994243a224477a75c78344fa6c0406e3b2de2 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 4 Jul 2023 10:34:27 +0200 Subject: [PATCH 02/22] extend comment --- compiler/rustc_trait_selection/src/traits/wf.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index b0798ace60dff..ae7236e30f553 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -304,6 +304,11 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { fn normalize(self, infcx: &InferCtxt<'tcx>) -> Vec> { // Do not normalize `wf` obligations with the new solver. + // + // The current deep normalization routine with the new solver does not + // handle ambiguity and the new solver correctly deals with unnnormalized goals. + // If the user relies on normalized types, e.g. for `fn implied_outlives_bounds`, + // it is their responsibility to normalize while avoiding ambiguity. if infcx.next_trait_solver() { return self.out; } From 594cd84a942eeea11c7a81cb410f5858b181f224 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 4 Jul 2023 11:50:51 +0200 Subject: [PATCH 03/22] `TypeParameterDefinition` always require a `DefId` --- .../src/fn_ctxt/adjust_fulfillment_errors.rs | 2 +- .../rustc_infer/src/infer/error_reporting/need_type_info.rs | 6 +++--- compiler/rustc_infer/src/infer/mod.rs | 2 +- compiler/rustc_infer/src/infer/type_variable.rs | 2 +- .../rustc_trait_selection/src/traits/error_reporting/mod.rs | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index 223aedefea3d6..ed9bb4945afc1 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -254,7 +254,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { type BreakTy = ty::GenericArg<'tcx>; fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow { if let Some(origin) = self.0.type_var_origin(ty) - && let rustc_infer::infer::type_variable::TypeVariableOriginKind::TypeParameterDefinition(_, Some(def_id)) = + && let rustc_infer::infer::type_variable::TypeVariableOriginKind::TypeParameterDefinition(_, def_id) = origin.kind && let generics = self.0.tcx.generics_of(self.1) && let Some(index) = generics.param_def_id_to_index(self.0.tcx, def_id) diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index f3b2ec4c5e383..bb75ecc6adbb3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -265,9 +265,9 @@ impl<'tcx> InferCtxt<'tcx> { kind: UnderspecifiedArgKind::Type { prefix: "type parameter".into(), }, - parent: def_id.and_then(|def_id| { - InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id) - }), + parent: InferenceDiagnosticsParentData::for_def_id( + self.tcx, def_id, + ), }; } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index f1f5ac81fb7db..29a6b2dc63b0f 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1110,7 +1110,7 @@ impl<'tcx> InferCtxt<'tcx> { TypeVariableOrigin { kind: TypeVariableOriginKind::TypeParameterDefinition( param.name, - Some(param.def_id), + param.def_id, ), span, }, diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs index 9f85f9207e8f2..01c11d16345fe 100644 --- a/compiler/rustc_infer/src/infer/type_variable.rs +++ b/compiler/rustc_infer/src/infer/type_variable.rs @@ -123,7 +123,7 @@ pub enum TypeVariableOriginKind { NormalizeProjectionType, TypeInference, OpaqueTypeInference(DefId), - TypeParameterDefinition(Symbol, Option), + TypeParameterDefinition(Symbol, DefId), /// One of the upvars or closure kind parameters in a `ClosureSubsts` /// (before it has been determined). 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 f7670d51bdc1d..547c6ed5a667e 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2642,11 +2642,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if let ty::Param(ty::ParamTy { name, .. }) = *ty.kind() { + if let ty::Param(_) = *ty.kind() { let infcx = self.infcx; *self.var_map.entry(ty).or_insert_with(|| { infcx.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeParameterDefinition(name, None), + kind: TypeVariableOriginKind::MiscVariable, span: DUMMY_SP, }) }) From f3d9248c222aea421ebf463cabcec893d7a773f4 Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 23 Jun 2023 10:34:06 +0300 Subject: [PATCH 04/22] rust-installer and rls no longer submodule, so fix rustfmt.toml --- rustfmt.toml | 4 +-- src/tools/rust-installer/src/combiner.rs | 25 +++++-------------- src/tools/rust-installer/src/generator.rs | 30 +++++------------------ src/tools/rust-installer/src/main.rs | 8 ++++-- src/tools/rust-installer/src/scripter.rs | 5 +--- src/tools/rust-installer/src/tarballer.rs | 11 ++------- src/tools/rust-installer/src/util.rs | 17 ++++++------- 7 files changed, 31 insertions(+), 69 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index 597ef5b90529e..88700779e87be 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -16,6 +16,8 @@ ignore = [ "tests", # do not format submodules + # FIXME: sync submodule list with tidy/bootstrap/etc + # tidy/src/walk.rs:filter_dirs "library/backtrace", "library/portable-simd", "library/stdarch", @@ -31,10 +33,8 @@ ignore = [ "src/tools/cargo", "src/tools/clippy", "src/tools/miri", - "src/tools/rls", "src/tools/rust-analyzer", "src/tools/rustfmt", - "src/tools/rust-installer", # these are ignored by a standard cargo fmt run "compiler/rustc_codegen_cranelift/y.rs", # running rustfmt breaks this file diff --git a/src/tools/rust-installer/src/combiner.rs b/src/tools/rust-installer/src/combiner.rs index 19466f63fedf0..565d19d863f64 100644 --- a/src/tools/rust-installer/src/combiner.rs +++ b/src/tools/rust-installer/src/combiner.rs @@ -71,25 +71,16 @@ impl Combiner { // Merge each installer into the work directory of the new installer. let components = create_new_file(package_dir.join("components"))?; - for input_tarball in self - .input_tarballs - .split(',') - .map(str::trim) - .filter(|s| !s.is_empty()) + for input_tarball in self.input_tarballs.split(',').map(str::trim).filter(|s| !s.is_empty()) { // Extract the input tarballs let compression = CompressionFormat::detect_from_path(input_tarball).ok_or_else(|| { anyhow::anyhow!("couldn't figure out the format of {}", input_tarball) })?; - Archive::new(compression.decode(input_tarball)?) - .unpack(&self.work_dir) - .with_context(|| { - format!( - "unable to extract '{}' into '{}'", - &input_tarball, self.work_dir - ) - })?; + Archive::new(compression.decode(input_tarball)?).unpack(&self.work_dir).with_context( + || format!("unable to extract '{}' into '{}'", &input_tarball, self.work_dir), + )?; let pkg_name = input_tarball.trim_end_matches(&format!(".tar.{}", compression.extension())); @@ -126,12 +117,8 @@ impl Combiner { // Write the installer version. let version = package_dir.join("rust-installer-version"); - writeln!( - create_new_file(version)?, - "{}", - crate::RUST_INSTALLER_VERSION - ) - .context("failed to write new installer version")?; + writeln!(create_new_file(version)?, "{}", crate::RUST_INSTALLER_VERSION) + .context("failed to write new installer version")?; // Copy the overlay. if !self.non_installed_overlay.is_empty() { diff --git a/src/tools/rust-installer/src/generator.rs b/src/tools/rust-installer/src/generator.rs index 45f8c49d03eaf..b101e67d8df7f 100644 --- a/src/tools/rust-installer/src/generator.rs +++ b/src/tools/rust-installer/src/generator.rs @@ -86,12 +86,8 @@ impl Generator { // Write the installer version (only used by combine-installers.sh) let version = package_dir.join("rust-installer-version"); - writeln!( - create_new_file(version)?, - "{}", - crate::RUST_INSTALLER_VERSION - ) - .context("failed to write new installer version")?; + writeln!(create_new_file(version)?, "{}", crate::RUST_INSTALLER_VERSION) + .context("failed to write new installer version")?; // Copy the overlay if !self.non_installed_overlay.is_empty() { @@ -128,33 +124,19 @@ impl Generator { /// Copies the `src` directory recursively to `dst`, writing `manifest.in` too. fn copy_and_manifest(src: &Path, dst: &Path, bulk_dirs: &str) -> Result<()> { let mut manifest = create_new_file(dst.join("manifest.in"))?; - let bulk_dirs: Vec<_> = bulk_dirs - .split(',') - .filter(|s| !s.is_empty()) - .map(Path::new) - .collect(); + let bulk_dirs: Vec<_> = bulk_dirs.split(',').filter(|s| !s.is_empty()).map(Path::new).collect(); let mut paths = BTreeSet::new(); copy_with_callback(src, dst, |path, file_type| { // We need paths to be compatible with both Unix and Windows. - if path - .components() - .filter_map(|c| c.as_os_str().to_str()) - .any(|s| s.contains('\\')) - { - bail!( - "rust-installer doesn't support '\\' in path components: {:?}", - path - ); + if path.components().filter_map(|c| c.as_os_str().to_str()).any(|s| s.contains('\\')) { + bail!("rust-installer doesn't support '\\' in path components: {:?}", path); } // Normalize to Unix-style path separators. let normalized_string; let mut string = path.to_str().ok_or_else(|| { - format_err!( - "rust-installer doesn't support non-Unicode paths: {:?}", - path - ) + format_err!("rust-installer doesn't support non-Unicode paths: {:?}", path) })?; if string.contains('\\') { normalized_string = string.replace('\\', "/"); diff --git a/src/tools/rust-installer/src/main.rs b/src/tools/rust-installer/src/main.rs index be8a0d68343e4..99acecdd43c35 100644 --- a/src/tools/rust-installer/src/main.rs +++ b/src/tools/rust-installer/src/main.rs @@ -19,8 +19,12 @@ fn main() -> Result<()> { let command_line = CommandLine::parse(); match command_line.command { Subcommand::Combine(combiner) => combiner.run().context("failed to combine installers")?, - Subcommand::Generate(generator) => generator.run().context("failed to generate installer")?, - Subcommand::Script(scripter) => scripter.run().context("failed to generate installation script")?, + Subcommand::Generate(generator) => { + generator.run().context("failed to generate installer")? + } + Subcommand::Script(scripter) => { + scripter.run().context("failed to generate installation script")? + } Subcommand::Tarball(tarballer) => tarballer.run().context("failed to generate tarballs")?, } Ok(()) diff --git a/src/tools/rust-installer/src/scripter.rs b/src/tools/rust-installer/src/scripter.rs index 8180f925cb0d5..3ce2d68c8bd17 100644 --- a/src/tools/rust-installer/src/scripter.rs +++ b/src/tools/rust-installer/src/scripter.rs @@ -44,10 +44,7 @@ impl Scripter { .replace("%%TEMPLATE_PRODUCT_NAME%%", &sh_quote(&product_name)) .replace("%%TEMPLATE_REL_MANIFEST_DIR%%", &self.rel_manifest_dir) .replace("%%TEMPLATE_SUCCESS_MESSAGE%%", &sh_quote(&success_message)) - .replace( - "%%TEMPLATE_LEGACY_MANIFEST_DIRS%%", - &sh_quote(&self.legacy_manifest_dirs), - ) + .replace("%%TEMPLATE_LEGACY_MANIFEST_DIRS%%", &sh_quote(&self.legacy_manifest_dirs)) .replace( "%%TEMPLATE_RUST_INSTALLER_VERSION%%", &sh_quote(&crate::RUST_INSTALLER_VERSION), diff --git a/src/tools/rust-installer/src/tarballer.rs b/src/tools/rust-installer/src/tarballer.rs index c60d5f648ffca..7572dc6dcf885 100644 --- a/src/tools/rust-installer/src/tarballer.rs +++ b/src/tools/rust-installer/src/tarballer.rs @@ -58,10 +58,7 @@ impl Tarballer { let buf = BufWriter::with_capacity(1024 * 1024, encoder); let mut builder = Builder::new(buf); - let pool = rayon::ThreadPoolBuilder::new() - .num_threads(2) - .build() - .unwrap(); + let pool = rayon::ThreadPoolBuilder::new().num_threads(2).build().unwrap(); pool.install(move || { for path in dirs { let src = Path::new(&self.work_dir).join(&path); @@ -122,11 +119,7 @@ where let name = name.as_ref(); if !name.is_relative() && !name.starts_with(root) { - bail!( - "input '{}' is not in work dir '{}'", - name.display(), - root.display() - ); + bail!("input '{}' is not in work dir '{}'", name.display(), root.display()); } let mut dirs = vec![]; diff --git a/src/tools/rust-installer/src/util.rs b/src/tools/rust-installer/src/util.rs index 4eb2e75fd7e1a..47ca0cfa3cc12 100644 --- a/src/tools/rust-installer/src/util.rs +++ b/src/tools/rust-installer/src/util.rs @@ -15,8 +15,7 @@ use std::os::windows::fs::symlink_file; /// Converts a `&Path` to a UTF-8 `&str`. pub fn path_to_str(path: &Path) -> Result<&str> { - path.to_str() - .ok_or_else(|| format_err!("path is not valid UTF-8 '{}'", path.display())) + path.to_str().ok_or_else(|| format_err!("path is not valid UTF-8 '{}'", path.display())) } /// Wraps `fs::copy` with a nicer error message. @@ -27,11 +26,7 @@ pub fn copy, Q: AsRef>(from: P, to: Q) -> Result { Ok(0) } else { let amt = fs::copy(&from, &to).with_context(|| { - format!( - "failed to copy '{}' to '{}'", - from.as_ref().display(), - to.as_ref().display() - ) + format!("failed to copy '{}' to '{}'", from.as_ref().display(), to.as_ref().display()) })?; Ok(amt) } @@ -123,8 +118,12 @@ where } macro_rules! actor_field_default { - () => { Default::default() }; - (= $expr:expr) => { $expr.into() } + () => { + Default::default() + }; + (= $expr:expr) => { + $expr.into() + }; } /// Creates an "actor" with default values, setters for all fields, and Clap parser support. From d9f77c74fd269db0de8e15c04eb56a6866b824c8 Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 23 Jun 2023 10:50:10 +0300 Subject: [PATCH 05/22] rust-installer and rls no longer submodule, so fix tidy walk list --- src/tools/tidy/src/walk.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/tidy/src/walk.rs b/src/tools/tidy/src/walk.rs index 3539943ebefe2..185e1f3209b10 100644 --- a/src/tools/tidy/src/walk.rs +++ b/src/tools/tidy/src/walk.rs @@ -4,6 +4,8 @@ use std::{ffi::OsStr, fs::File, io::Read, path::Path}; /// The default directory filter. pub fn filter_dirs(path: &Path) -> bool { + // FIXME: sync submodule exclusion list with rustfmt.toml + // bootstrap/etc let skip = [ "tidy-test-file", "compiler/rustc_codegen_cranelift", @@ -15,9 +17,7 @@ pub fn filter_dirs(path: &Path) -> bool { "src/tools/cargo", "src/tools/clippy", "src/tools/miri", - "src/tools/rls", "src/tools/rust-analyzer", - "src/tools/rust-installer", "src/tools/rustfmt", "src/doc/book", "src/doc/edition-guide", From 02e9262c11148af89028407132380d75a96006eb Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 23 Jun 2023 12:09:22 +0300 Subject: [PATCH 06/22] replace tabs with 4 spaces in .sh --- src/tools/rust-installer/install-template.sh | 598 +++++------ src/tools/rust-installer/test.sh | 1010 +++++++++--------- 2 files changed, 804 insertions(+), 804 deletions(-) diff --git a/src/tools/rust-installer/install-template.sh b/src/tools/rust-installer/install-template.sh index 92a3f1f2c983a..9246e5b7f5aed 100644 --- a/src/tools/rust-installer/install-template.sh +++ b/src/tools/rust-installer/install-template.sh @@ -17,8 +17,8 @@ log_line() { local _line="$1" if [ -n "${LOGFILE-}" -a -e "${LOGFILE-}" ]; then - echo "$_line" >> "$LOGFILE" - # Ignore errors, which may happen e.g. after the manifest dir is deleted + echo "$_line" >> "$LOGFILE" + # Ignore errors, which may happen e.g. after the manifest dir is deleted fi } @@ -30,9 +30,9 @@ msg() { verbose_msg() { if [ -n "${CFG_VERBOSE-}" ]; then - msg "${1-}" + msg "${1-}" else - log_line "install: ${1-}" + log_line "install: ${1-}" fi } @@ -44,13 +44,13 @@ step_msg() { verbose_step_msg() { if [ -n "${CFG_VERBOSE-}" ]; then - msg - msg "$1" - msg + msg + msg "$1" + msg else - log_line "" - log_line "install: $1" - log_line "" + log_line "" + log_line "install: $1" + log_line "" fi } @@ -91,7 +91,7 @@ critical_need_ok() { want_ok() { if [ $? -ne 0 ]; then - warn "$1" + warn "$1" fi } @@ -321,40 +321,40 @@ uninstall_legacy() { # Uninstall from legacy manifests local _md for _md in $_legacy_manifest_dirs; do - # First, uninstall from the installation prefix. - # Errors are warnings - try to rm everything in the manifest even if some fail. - if [ -f "$_abs_libdir/$_md/manifest" ] - then - - # iterate through installed manifest and remove files - local _p; - while read _p; do - # the installed manifest contains absolute paths - msg "removing legacy file $_p" - if [ -f "$_p" ] - then - run rm -f "$_p" - want_ok "failed to remove $_p" - else - warn "supposedly installed file $_p does not exist!" - fi - done < "$_abs_libdir/$_md/manifest" - - # If we fail to remove $md below, then the - # installed manifest will still be full; the installed manifest - # needs to be empty before install. - msg "removing legacy manifest $_abs_libdir/$_md/manifest" - run rm -f "$_abs_libdir/$_md/manifest" - # For the above reason, this is a hard error - need_ok "failed to remove installed manifest" - - # Remove $template_rel_manifest_dir directory - msg "removing legacy manifest dir $_abs_libdir/$_md" - run rm -R "$_abs_libdir/$_md" - want_ok "failed to remove $_md" - - _uninstalled_something=true - fi + # First, uninstall from the installation prefix. + # Errors are warnings - try to rm everything in the manifest even if some fail. + if [ -f "$_abs_libdir/$_md/manifest" ] + then + + # iterate through installed manifest and remove files + local _p; + while read _p; do + # the installed manifest contains absolute paths + msg "removing legacy file $_p" + if [ -f "$_p" ] + then + run rm -f "$_p" + want_ok "failed to remove $_p" + else + warn "supposedly installed file $_p does not exist!" + fi + done < "$_abs_libdir/$_md/manifest" + + # If we fail to remove $md below, then the + # installed manifest will still be full; the installed manifest + # needs to be empty before install. + msg "removing legacy manifest $_abs_libdir/$_md/manifest" + run rm -f "$_abs_libdir/$_md/manifest" + # For the above reason, this is a hard error + need_ok "failed to remove installed manifest" + + # Remove $template_rel_manifest_dir directory + msg "removing legacy manifest dir $_abs_libdir/$_md" + run rm -R "$_abs_libdir/$_md" + want_ok "failed to remove $_md" + + _uninstalled_something=true + fi done RETVAL="$_uninstalled_something" @@ -373,133 +373,133 @@ uninstall_components() { uninstall_legacy "$_abs_libdir" assert_nz "$RETVAL", "RETVAL" if [ "$RETVAL" = true ]; then - _uninstalled_something=true; + _uninstalled_something=true; fi # Load the version of the installed installer local _installed_version= if [ -f "$abs_libdir/$TEMPLATE_REL_MANIFEST_DIR/rust-installer-version" ]; then - _installed_version=`cat "$_abs_libdir/$TEMPLATE_REL_MANIFEST_DIR/rust-installer-version"` + _installed_version=`cat "$_abs_libdir/$TEMPLATE_REL_MANIFEST_DIR/rust-installer-version"` - # Sanity check - if [ ! -n "$_installed_version" ]; then critical_err "rust installer version is empty"; fi + # Sanity check + if [ ! -n "$_installed_version" ]; then critical_err "rust installer version is empty"; fi fi # If there's something installed, then uninstall if [ -n "$_installed_version" ]; then - # Check the version of the installed installer - case "$_installed_version" in - - # If this is a previous version, then upgrade in place to the - # current version before uninstalling. - 2 ) - # The only change between version 2 -> 3 is that components are placed - # in subdirectories of the installer tarball. There are no changes - # to the installed data format, so nothing to do. - ;; - - # This is the current version. Nothing need to be done except uninstall. - "$TEMPLATE_RUST_INSTALLER_VERSION") - ;; - - # If this is an unknown (future) version then bail. - * ) - echo "The copy of $TEMPLATE_PRODUCT_NAME at $_dest_prefix was installed using an" - echo "unknown version ($_installed_version) of rust-installer." - echo "Uninstall it first with the installer used for the original installation" - echo "before continuing." - exit 1 - ;; - esac - - local _md="$_abs_libdir/$TEMPLATE_REL_MANIFEST_DIR" - local _installed_components="$(cat "$_md/components")" - - # Uninstall (our components only) before reinstalling - local _available_component - for _available_component in $_components; do - local _installed_component - for _installed_component in $_installed_components; do - if [ "$_available_component" = "$_installed_component" ]; then - msg "uninstalling component '$_available_component'" - local _component_manifest="$_md/manifest-$_installed_component" - - # Sanity check: there should be a component manifest - if [ ! -f "$_component_manifest" ]; then - critical_err "installed component '$_installed_component' has no manifest" - fi - - # Iterate through installed component manifest and remove files - local _directive - while read _directive; do - - local _command=`echo $_directive | cut -f1 -d:` - local _file=`echo $_directive | cut -f2 -d:` - - # Sanity checks - if [ ! -n "$_command" ]; then critical_err "malformed installation directive"; fi - if [ ! -n "$_file" ]; then critical_err "malformed installation directive"; fi - - case "$_command" in - file) - verbose_msg "removing file $_file" - if [ -f "$_file" ]; then - run rm -f "$_file" - want_ok "failed to remove $_file" - else - warn "supposedly installed file $_file does not exist!" - fi - ;; - - dir) - verbose_msg "removing directory $_file" - run rm -r "$_file" - want_ok "unable to remove directory $_file" - ;; - - *) - critical_err "unknown installation directive" - ;; - esac - - done < "$_component_manifest" - - # Remove the installed component manifest - verbose_msg "removing component manifest $_component_manifest" - run rm "$_component_manifest" - # This is a hard error because the installation is unrecoverable - critical_need_ok "failed to remove installed manifest for component '$_installed_component'" - - # Update the installed component list - local _modified_components="$(sed "/^$_installed_component\$/d" "$_md/components")" - write_to_file "$_modified_components" "$_md/components" - critical_need_ok "failed to update installed component list" - fi - done - done - - # If there are no remaining components delete the manifest directory, - # but only if we're doing an uninstall - if we're doing an install, - # then leave the manifest directory around to hang onto the logs, - # and any files not managed by the installer. - if [ -n "${CFG_UNINSTALL-}" ]; then - local _remaining_components="$(cat "$_md/components")" - if [ ! -n "$_remaining_components" ]; then - verbose_msg "removing manifest directory $_md" - run rm -r "$_md" - want_ok "failed to remove $_md" - - maybe_unconfigure_ld - fi - fi - - _uninstalled_something=true + # Check the version of the installed installer + case "$_installed_version" in + + # If this is a previous version, then upgrade in place to the + # current version before uninstalling. + 2 ) + # The only change between version 2 -> 3 is that components are placed + # in subdirectories of the installer tarball. There are no changes + # to the installed data format, so nothing to do. + ;; + + # This is the current version. Nothing need to be done except uninstall. + "$TEMPLATE_RUST_INSTALLER_VERSION") + ;; + + # If this is an unknown (future) version then bail. + * ) + echo "The copy of $TEMPLATE_PRODUCT_NAME at $_dest_prefix was installed using an" + echo "unknown version ($_installed_version) of rust-installer." + echo "Uninstall it first with the installer used for the original installation" + echo "before continuing." + exit 1 + ;; + esac + + local _md="$_abs_libdir/$TEMPLATE_REL_MANIFEST_DIR" + local _installed_components="$(cat "$_md/components")" + + # Uninstall (our components only) before reinstalling + local _available_component + for _available_component in $_components; do + local _installed_component + for _installed_component in $_installed_components; do + if [ "$_available_component" = "$_installed_component" ]; then + msg "uninstalling component '$_available_component'" + local _component_manifest="$_md/manifest-$_installed_component" + + # Sanity check: there should be a component manifest + if [ ! -f "$_component_manifest" ]; then + critical_err "installed component '$_installed_component' has no manifest" + fi + + # Iterate through installed component manifest and remove files + local _directive + while read _directive; do + + local _command=`echo $_directive | cut -f1 -d:` + local _file=`echo $_directive | cut -f2 -d:` + + # Sanity checks + if [ ! -n "$_command" ]; then critical_err "malformed installation directive"; fi + if [ ! -n "$_file" ]; then critical_err "malformed installation directive"; fi + + case "$_command" in + file) + verbose_msg "removing file $_file" + if [ -f "$_file" ]; then + run rm -f "$_file" + want_ok "failed to remove $_file" + else + warn "supposedly installed file $_file does not exist!" + fi + ;; + + dir) + verbose_msg "removing directory $_file" + run rm -r "$_file" + want_ok "unable to remove directory $_file" + ;; + + *) + critical_err "unknown installation directive" + ;; + esac + + done < "$_component_manifest" + + # Remove the installed component manifest + verbose_msg "removing component manifest $_component_manifest" + run rm "$_component_manifest" + # This is a hard error because the installation is unrecoverable + critical_need_ok "failed to remove installed manifest for component '$_installed_component'" + + # Update the installed component list + local _modified_components="$(sed "/^$_installed_component\$/d" "$_md/components")" + write_to_file "$_modified_components" "$_md/components" + critical_need_ok "failed to update installed component list" + fi + done + done + + # If there are no remaining components delete the manifest directory, + # but only if we're doing an uninstall - if we're doing an install, + # then leave the manifest directory around to hang onto the logs, + # and any files not managed by the installer. + if [ -n "${CFG_UNINSTALL-}" ]; then + local _remaining_components="$(cat "$_md/components")" + if [ ! -n "$_remaining_components" ]; then + verbose_msg "removing manifest directory $_md" + run rm -r "$_md" + want_ok "failed to remove $_md" + + maybe_unconfigure_ld + fi + fi + + _uninstalled_something=true fi # There's no installed version. If we were asked to uninstall, then that's a problem. if [ -n "${CFG_UNINSTALL-}" -a "$_uninstalled_something" = false ] then - err "unable to find installation manifest at $CFG_LIBDIR/$TEMPLATE_REL_MANIFEST_DIR" + err "unable to find installation manifest at $CFG_LIBDIR/$TEMPLATE_REL_MANIFEST_DIR" fi } @@ -512,73 +512,73 @@ install_components() { local _component for _component in $_components; do - msg "installing component '$_component'" + msg "installing component '$_component'" - # The file name of the manifest we're installing from - local _input_manifest="$_src_dir/$_component/manifest.in" + # The file name of the manifest we're installing from + local _input_manifest="$_src_dir/$_component/manifest.in" - # Sanity check: do we have our input manifests? - if [ ! -f "$_input_manifest" ]; then - critical_err "manifest for $_component does not exist at $_input_manifest" - fi + # Sanity check: do we have our input manifests? + if [ ! -f "$_input_manifest" ]; then + critical_err "manifest for $_component does not exist at $_input_manifest" + fi - # The installed manifest directory - local _md="$_abs_libdir/$TEMPLATE_REL_MANIFEST_DIR" + # The installed manifest directory + local _md="$_abs_libdir/$TEMPLATE_REL_MANIFEST_DIR" - # The file name of the manifest we're going to create during install - local _installed_manifest="$_md/manifest-$_component" + # The file name of the manifest we're going to create during install + local _installed_manifest="$_md/manifest-$_component" - # Create the installed manifest, which we will fill in with absolute file paths - touch "$_installed_manifest" - critical_need_ok "failed to create installed manifest" + # Create the installed manifest, which we will fill in with absolute file paths + touch "$_installed_manifest" + critical_need_ok "failed to create installed manifest" - # Add this component to the installed component list - append_to_file "$_component" "$_md/components" - critical_need_ok "failed to update components list for $_component" + # Add this component to the installed component list + append_to_file "$_component" "$_md/components" + critical_need_ok "failed to update components list for $_component" - # Now install, iterate through the new manifest and copy files - local _directive - while read _directive; do + # Now install, iterate through the new manifest and copy files + local _directive + while read _directive; do - local _command=`echo $_directive | cut -f1 -d:` - local _file=`echo $_directive | cut -f2 -d:` + local _command=`echo $_directive | cut -f1 -d:` + local _file=`echo $_directive | cut -f2 -d:` - # Sanity checks - if [ ! -n "$_command" ]; then critical_err "malformed installation directive"; fi - if [ ! -n "$_file" ]; then critical_err "malformed installation directive"; fi + # Sanity checks + if [ ! -n "$_command" ]; then critical_err "malformed installation directive"; fi + if [ ! -n "$_file" ]; then critical_err "malformed installation directive"; fi - # Decide the destination of the file - local _file_install_path="$_dest_prefix/$_file" + # Decide the destination of the file + local _file_install_path="$_dest_prefix/$_file" - if echo "$_file" | grep "^etc/" > /dev/null - then - local _f="$(echo "$_file" | sed 's/^etc\///')" - _file_install_path="$CFG_SYSCONFDIR/$_f" - fi + if echo "$_file" | grep "^etc/" > /dev/null + then + local _f="$(echo "$_file" | sed 's/^etc\///')" + _file_install_path="$CFG_SYSCONFDIR/$_f" + fi - if echo "$_file" | grep "^bin/" > /dev/null - then - local _f="$(echo "$_file" | sed 's/^bin\///')" - _file_install_path="$CFG_BINDIR/$_f" - fi + if echo "$_file" | grep "^bin/" > /dev/null + then + local _f="$(echo "$_file" | sed 's/^bin\///')" + _file_install_path="$CFG_BINDIR/$_f" + fi - if echo "$_file" | grep "^lib/" > /dev/null - then - local _f="$(echo "$_file" | sed 's/^lib\///')" - _file_install_path="$CFG_LIBDIR/$_f" - fi + if echo "$_file" | grep "^lib/" > /dev/null + then + local _f="$(echo "$_file" | sed 's/^lib\///')" + _file_install_path="$CFG_LIBDIR/$_f" + fi - if echo "$_file" | grep "^share" > /dev/null - then - local _f="$(echo "$_file" | sed 's/^share\///')" - _file_install_path="$CFG_DATADIR/$_f" - fi + if echo "$_file" | grep "^share" > /dev/null + then + local _f="$(echo "$_file" | sed 's/^share\///')" + _file_install_path="$CFG_DATADIR/$_f" + fi - if echo "$_file" | grep "^share/man/" > /dev/null - then - local _f="$(echo "$_file" | sed 's/^share\/man\///')" - _file_install_path="$CFG_MANDIR/$_f" - fi + if echo "$_file" | grep "^share/man/" > /dev/null + then + local _f="$(echo "$_file" | sed 's/^share\/man\///')" + _file_install_path="$CFG_MANDIR/$_f" + fi # HACK: Try to support overriding --docdir. Paths with the form # "share/doc/$product/" can be redirected to a single --docdir @@ -592,69 +592,69 @@ install_components() { # this problem to be a big deal in practice. if [ "$CFG_DOCDIR" != "" ] then - if echo "$_file" | grep "^share/doc/" > /dev/null - then - local _f="$(echo "$_file" | sed 's/^share\/doc\/[^/]*\///')" - _file_install_path="$CFG_DOCDIR/$_f" - fi + if echo "$_file" | grep "^share/doc/" > /dev/null + then + local _f="$(echo "$_file" | sed 's/^share\/doc\/[^/]*\///')" + _file_install_path="$CFG_DOCDIR/$_f" + fi fi - # Make sure there's a directory for it - make_dir_recursive "$(dirname "$_file_install_path")" - critical_need_ok "directory creation failed" + # Make sure there's a directory for it + make_dir_recursive "$(dirname "$_file_install_path")" + critical_need_ok "directory creation failed" - # Make the path absolute so we can uninstall it later without - # starting from the installation cwd - absolutify "$_file_install_path" - _file_install_path="$RETVAL" - assert_nz "$_file_install_path" "file_install_path" + # Make the path absolute so we can uninstall it later without + # starting from the installation cwd + absolutify "$_file_install_path" + _file_install_path="$RETVAL" + assert_nz "$_file_install_path" "file_install_path" - case "$_command" in - file ) + case "$_command" in + file ) - verbose_msg "copying file $_file_install_path" + verbose_msg "copying file $_file_install_path" - maybe_backup_path "$_file_install_path" + maybe_backup_path "$_file_install_path" - if echo "$_file" | grep "^bin/" > /dev/null || test -x "$_src_dir/$_component/$_file" - then - run cp "$_src_dir/$_component/$_file" "$_file_install_path" - run chmod 755 "$_file_install_path" - else - run cp "$_src_dir/$_component/$_file" "$_file_install_path" - run chmod 644 "$_file_install_path" - fi - critical_need_ok "file creation failed" + if echo "$_file" | grep "^bin/" > /dev/null || test -x "$_src_dir/$_component/$_file" + then + run cp "$_src_dir/$_component/$_file" "$_file_install_path" + run chmod 755 "$_file_install_path" + else + run cp "$_src_dir/$_component/$_file" "$_file_install_path" + run chmod 644 "$_file_install_path" + fi + critical_need_ok "file creation failed" - # Update the manifest - append_to_file "file:$_file_install_path" "$_installed_manifest" - critical_need_ok "failed to update manifest" + # Update the manifest + append_to_file "file:$_file_install_path" "$_installed_manifest" + critical_need_ok "failed to update manifest" - ;; + ;; - dir ) + dir ) - verbose_msg "copying directory $_file_install_path" + verbose_msg "copying directory $_file_install_path" - maybe_backup_path "$_file_install_path" + maybe_backup_path "$_file_install_path" - run cp -R "$_src_dir/$_component/$_file" "$_file_install_path" - critical_need_ok "failed to copy directory" + run cp -R "$_src_dir/$_component/$_file" "$_file_install_path" + critical_need_ok "failed to copy directory" # Set permissions. 0755 for dirs, 644 for files run chmod -R u+rwX,go+rX,go-w "$_file_install_path" critical_need_ok "failed to set permissions on directory" - # Update the manifest - append_to_file "dir:$_file_install_path" "$_installed_manifest" - critical_need_ok "failed to update manifest" - ;; + # Update the manifest + append_to_file "dir:$_file_install_path" "$_installed_manifest" + critical_need_ok "failed to update manifest" + ;; - *) - critical_err "unknown installation directive" - ;; - esac - done < "$_input_manifest" + *) + critical_err "unknown installation directive" + ;; + esac + done < "$_input_manifest" done } @@ -667,33 +667,33 @@ maybe_configure_ld() { if [ "$_ostype" = "Linux" -a ! -n "${CFG_DISABLE_LDCONFIG-}" ]; then - # Fedora-based systems do not configure the dynamic linker to look - # /usr/local/lib, which is our default installation directory. To - # make things just work, try to put that directory in - # /etc/ld.so.conf.d/rust-installer-v1 so ldconfig picks it up. - # Issue #30. - # - # This will get rm'd when the last component is uninstalled in - # maybe_unconfigure_ld. - if [ "$_abs_libdir" = "/usr/local/lib" -a -d "/etc/ld.so.conf.d" ]; then - echo "$_abs_libdir" > "/etc/ld.so.conf.d/rust-installer-v1-$TEMPLATE_REL_MANIFEST_DIR.conf" - if [ $? -ne 0 ]; then - # This shouldn't happen if we've gotten this far - # installing to /usr/local - warn "failed to update /etc/ld.so.conf.d. this is unexpected" - fi - fi - - verbose_msg "running ldconfig" - if [ -n "${CFG_VERBOSE-}" ]; then - ldconfig - else - ldconfig 2> /dev/null - fi - if [ $? -ne 0 ] - then + # Fedora-based systems do not configure the dynamic linker to look + # /usr/local/lib, which is our default installation directory. To + # make things just work, try to put that directory in + # /etc/ld.so.conf.d/rust-installer-v1 so ldconfig picks it up. + # Issue #30. + # + # This will get rm'd when the last component is uninstalled in + # maybe_unconfigure_ld. + if [ "$_abs_libdir" = "/usr/local/lib" -a -d "/etc/ld.so.conf.d" ]; then + echo "$_abs_libdir" > "/etc/ld.so.conf.d/rust-installer-v1-$TEMPLATE_REL_MANIFEST_DIR.conf" + if [ $? -ne 0 ]; then + # This shouldn't happen if we've gotten this far + # installing to /usr/local + warn "failed to update /etc/ld.so.conf.d. this is unexpected" + fi + fi + + verbose_msg "running ldconfig" + if [ -n "${CFG_VERBOSE-}" ]; then + ldconfig + else + ldconfig 2> /dev/null + fi + if [ $? -ne 0 ] + then warn "failed to run ldconfig. this may happen when not installing as root. run with --verbose to see the error" - fi + fi fi } @@ -702,7 +702,7 @@ maybe_unconfigure_ld() { assert_nz "$_ostype" "ostype" if [ "$_ostype" != "Linux" ]; then - return 0 + return 0 fi rm "/etc/ld.so.conf.d/rust-installer-v1-$TEMPLATE_REL_MANIFEST_DIR.conf" 2> /dev/null @@ -714,9 +714,9 @@ maybe_backup_path() { local _file_install_path="$1" if [ -e "$_file_install_path" ]; then - msg "backing up existing file at $_file_install_path" - run mv -f "$_file_install_path" "$_file_install_path.old" - critical_need_ok "failed to back up $_file_install_path" + msg "backing up existing file at $_file_install_path" + run mv -f "$_file_install_path" "$_file_install_path.old" + critical_need_ok "failed to back up $_file_install_path" fi } @@ -742,7 +742,7 @@ do_preflight_sanity_checks() { touch "$CFG_LIBDIR/rust-install-probe" > /dev/null if [ $? -ne 0 ] then - err "can't write to destination. consider \`sudo\`." + err "can't write to destination. consider \`sudo\`." fi rm "$CFG_LIBDIR/rust-install-probe" need_ok "failed to remove install probe" @@ -752,7 +752,7 @@ do_preflight_sanity_checks() { verbose_msg "verifying destination is not the same as source" local _prefix_dir="$(abs_path "$dest_prefix")" if [ "$_src_dir" = "$_dest_prefix" -a "${CFG_UNINSTALL-}" != 1 ]; then - err "cannot install to same directory as installer" + err "cannot install to same directory as installer" fi } @@ -857,8 +857,8 @@ src_basename="$(basename "$0")" # which just means 'uninstall my components'. if [ "$src_basename" = "uninstall.sh" ]; then if [ "${*:-}" != "" ]; then - # Currently don't know what to do with arguments in this mode - err "uninstall.sh does not take any arguments" + # Currently don't know what to do with arguments in this mode + err "uninstall.sh does not take any arguments" fi CFG_UNINSTALL=1 CFG_DESTDIR_PREFIX="$(abs_path "$src_dir/../../")" @@ -885,7 +885,7 @@ if [ -n "${CFG_LIST_COMPONENTS-}" ]; then echo "# Available components" echo for component in $components; do - echo "* $component" + echo "* $component" done echo exit 0 @@ -897,15 +897,15 @@ if [ -n "$CFG_COMPONENTS" ]; then # Remove commas user_components="$(echo "$CFG_COMPONENTS" | sed "s/,/ /g")" for user_component in $user_components; do - found=false - for my_component in $components; do - if [ "$user_component" = "$my_component" ]; then - found=true - fi - done - if [ "$found" = false ]; then - err "unknown component: $user_component" - fi + found=false + for my_component in $components; do + if [ "$user_component" = "$my_component" ]; then + found=true + fi + done + if [ "$found" = false ]; then + err "unknown component: $user_component" + fi done components="$user_components" fi @@ -937,9 +937,9 @@ fi if [ -z "$components" ]; then if [ -z "${CFG_UNINSTALL-}" ]; then - err "no components selected for installation" + err "no components selected for installation" else - err "no components selected for uninstallation" + err "no components selected for uninstallation" fi fi diff --git a/src/tools/rust-installer/test.sh b/src/tools/rust-installer/test.sh index dac6f77ef1401..d6b0492eea866 100755 --- a/src/tools/rust-installer/test.sh +++ b/src/tools/rust-installer/test.sh @@ -27,7 +27,7 @@ PREFIX_DIR="$TMP_DIR/prefix" case $(uname -s) in MINGW* | MSYS*) - WINDOWS=1 + WINDOWS=1 ;; esac @@ -48,10 +48,10 @@ pre() { need_ok() { if [ $? -ne 0 ] then - echo - echo "TEST FAILED!" - echo - exit 1 + echo + echo "TEST FAILED!" + echo + exit 1 fi } @@ -69,20 +69,20 @@ try() { _cmd="$@" _output=`$@ 2>&1` if [ $? -ne 0 ]; then - echo \$ "$_cmd" - # Using /bin/echo to avoid escaping - $ECHO "$_output" - echo - echo "TEST FAILED!" - echo - exit 1 + echo \$ "$_cmd" + # Using /bin/echo to avoid escaping + $ECHO "$_output" + echo + echo "TEST FAILED!" + echo + exit 1 else - if [ -n "${VERBOSE-}" -o -n "${VERBOSE_CMD-}" ]; then - echo \$ "$_cmd" - fi - if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then - $ECHO "$_output" - fi + if [ -n "${VERBOSE-}" -o -n "${VERBOSE_CMD-}" ]; then + echo \$ "$_cmd" + fi + if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then + $ECHO "$_output" + fi fi set -e } @@ -92,20 +92,20 @@ expect_fail() { _cmd="$@" _output=`$@ 2>&1` if [ $? -eq 0 ]; then - echo \$ "$_cmd" - # Using /bin/echo to avoid escaping - $ECHO "$_output" - echo - echo "TEST FAILED!" - echo - exit 1 + echo \$ "$_cmd" + # Using /bin/echo to avoid escaping + $ECHO "$_output" + echo + echo "TEST FAILED!" + echo + exit 1 else - if [ -n "${VERBOSE-}" -o -n "${VERBOSE_CMD-}" ]; then - echo \$ "$_cmd" - fi - if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then - $ECHO "$_output" - fi + if [ -n "${VERBOSE-}" -o -n "${VERBOSE_CMD-}" ]; then + echo \$ "$_cmd" + fi + if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then + $ECHO "$_output" + fi fi set -e } @@ -117,30 +117,30 @@ expect_output_ok() { _cmd="$@" _output=`$@ 2>&1` if [ $? -ne 0 ]; then - echo \$ "$_cmd" - # Using /bin/echo to avoid escaping - $ECHO "$_output" - echo - echo "TEST FAILED!" - echo - exit 1 + echo \$ "$_cmd" + # Using /bin/echo to avoid escaping + $ECHO "$_output" + echo + echo "TEST FAILED!" + echo + exit 1 elif ! echo "$_output" | grep -q "$_expected"; then - echo \$ "$_cmd" - $ECHO "$_output" - echo - echo "missing expected output '$_expected'" - echo - echo - echo "TEST FAILED!" - echo - exit 1 + echo \$ "$_cmd" + $ECHO "$_output" + echo + echo "missing expected output '$_expected'" + echo + echo + echo "TEST FAILED!" + echo + exit 1 else - if [ -n "${VERBOSE-}" -o -n "${VERBOSE_CMD-}" ]; then - echo \$ "$_cmd" - fi - if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then - $ECHO "$_output" - fi + if [ -n "${VERBOSE-}" -o -n "${VERBOSE_CMD-}" ]; then + echo \$ "$_cmd" + fi + if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then + $ECHO "$_output" + fi fi set -e } @@ -152,30 +152,30 @@ expect_output_fail() { _cmd="$@" _output=`$@ 2>&1` if [ $? -eq 0 ]; then - echo \$ "$_cmd" - # Using /bin/echo to avoid escaping - $ECHO "$_output" - echo - echo "TEST FAILED!" - echo - exit 1 + echo \$ "$_cmd" + # Using /bin/echo to avoid escaping + $ECHO "$_output" + echo + echo "TEST FAILED!" + echo + exit 1 elif ! echo "$_output" | grep -q "$_expected"; then - echo \$ "$_cmd" - $ECHO "$_output" - echo - echo "missing expected output '$_expected'" - echo - echo - echo "TEST FAILED!" - echo - exit 1 + echo \$ "$_cmd" + $ECHO "$_output" + echo + echo "missing expected output '$_expected'" + echo + echo + echo "TEST FAILED!" + echo + exit 1 else - if [ -n "${VERBOSE-}" -o -n "${VERBOSE_CMD-}" ]; then - echo \$ "$_cmd" - fi - if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then - $ECHO "$_output" - fi + if [ -n "${VERBOSE-}" -o -n "${VERBOSE_CMD-}" ]; then + echo \$ "$_cmd" + fi + if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then + $ECHO "$_output" + fi fi set -e } @@ -187,30 +187,30 @@ expect_not_output_ok() { _cmd="$@" _output=`$@ 2>&1` if [ $? -ne 0 ]; then - echo \$ "$_cmd" - # Using /bin/echo to avoid escaping - $ECHO "$_output" - echo - echo "TEST FAILED!" - echo - exit 1 + echo \$ "$_cmd" + # Using /bin/echo to avoid escaping + $ECHO "$_output" + echo + echo "TEST FAILED!" + echo + exit 1 elif echo "$_output" | grep -q "$_expected"; then - echo \$ "$_cmd" - $ECHO "$_output" - echo - echo "unexpected output '$_expected'" - echo - echo - echo "TEST FAILED!" - echo - exit 1 + echo \$ "$_cmd" + $ECHO "$_output" + echo + echo "unexpected output '$_expected'" + echo + echo + echo "TEST FAILED!" + echo + exit 1 else - if [ -n "${VERBOSE-}" -o -n "${VERBOSE_CMD-}" ]; then - echo \$ "$_cmd" - fi - if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then - $ECHO "$_output" - fi + if [ -n "${VERBOSE-}" -o -n "${VERBOSE_CMD-}" ]; then + echo \$ "$_cmd" + fi + if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then + $ECHO "$_output" + fi fi set -e } @@ -218,9 +218,9 @@ expect_not_output_ok() { runtest() { local _testname="$1" if [ -n "${TESTNAME-}" ]; then - if ! echo "$_testname" | grep -q "$TESTNAME"; then - return 0 - fi + if ! echo "$_testname" | grep -q "$TESTNAME"; then + return 0 + fi fi pre "$_testname" @@ -231,9 +231,9 @@ runtest() { basic_install() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/something-to-install" try test -e "$PREFIX_DIR/dir-to-install/foo" @@ -245,9 +245,9 @@ runtest basic_install basic_uninstall() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" try "$WORK_DIR/package/install.sh --uninstall" --prefix="$PREFIX_DIR" try test ! -e "$PREFIX_DIR/something-to-install" @@ -263,10 +263,10 @@ not_installed_files() { mkdir -p "$WORK_DIR/overlay" touch "$WORK_DIR/overlay/not-installed" try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --non-installed-overlay="$WORK_DIR/overlay" + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --non-installed-overlay="$WORK_DIR/overlay" try test -e "$WORK_DIR/package/not-installed" try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" try test ! -e "$PREFIX_DIR/not-installed" @@ -275,10 +275,10 @@ runtest not_installed_files tarball_with_package_name() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc-nightly + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc-nightly try "$WORK_DIR/rustc-nightly/install.sh" --prefix="$PREFIX_DIR" try test -e "$OUT_DIR/rustc-nightly.tar.gz" try test -e "$OUT_DIR/rustc-nightly.tar.xz" @@ -287,9 +287,9 @@ runtest tarball_with_package_name install_overwrite_backup() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" try mkdir -p "$PREFIX_DIR/bin" touch "$PREFIX_DIR/bin/program" try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" @@ -300,10 +300,10 @@ runtest install_overwrite_backup bulk_directory() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --bulk-dirs=dir-to-install + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --bulk-dirs=dir-to-install try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/something-to-install" try test -e "$PREFIX_DIR/dir-to-install/foo" @@ -317,10 +317,10 @@ runtest bulk_directory bulk_directory_overwrite() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --bulk-dirs=dir-to-install + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --bulk-dirs=dir-to-install try mkdir -p "$PREFIX_DIR/dir-to-install" try touch "$PREFIX_DIR/dir-to-install/overwrite" try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" @@ -333,10 +333,10 @@ runtest bulk_directory_overwrite bulk_directory_overwrite_existing_backup() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --bulk-dirs=dir-to-install + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --bulk-dirs=dir-to-install try mkdir -p "$PREFIX_DIR/dir-to-install" try touch "$PREFIX_DIR/dir-to-install/overwrite" # This time we've already got an existing backup of the overwritten directory. @@ -351,10 +351,10 @@ runtest bulk_directory_overwrite_existing_backup nested_bulk_directory() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --bulk-dirs=dir-to-install/qux + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --bulk-dirs=dir-to-install/qux try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/dir-to-install/qux/bar" try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" --uninstall @@ -364,10 +364,10 @@ runtest nested_bulk_directory only_bulk_directory_no_files() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image5" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --bulk-dirs=dir-to-install + --image-dir="$TEST_DIR/image5" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --bulk-dirs=dir-to-install try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/dir-to-install/foo" try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" --uninstall @@ -379,10 +379,10 @@ nested_not_installed_files() { mkdir -p "$WORK_DIR/overlay" touch "$WORK_DIR/overlay/not-installed" try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --non-installed-overlay="$WORK_DIR/overlay" + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --non-installed-overlay="$WORK_DIR/overlay" try test -e "$WORK_DIR/package/not-installed" try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" try test ! -e "$PREFIX_DIR/not-installed" @@ -391,15 +391,15 @@ runtest nested_not_installed_files multiple_components() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR/c1" \ - --output-dir="$OUT_DIR/c1" \ - --component-name=rustc + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR/c1" \ + --output-dir="$OUT_DIR/c1" \ + --component-name=rustc try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR/c2" \ - --output-dir="$OUT_DIR/c2" \ - --component-name=cargo + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR/c2" \ + --output-dir="$OUT_DIR/c2" \ + --component-name=cargo try "$WORK_DIR/c1/package/install.sh" --prefix="$PREFIX_DIR" try "$WORK_DIR/c2/package/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/something-to-install" @@ -422,15 +422,15 @@ runtest multiple_components uninstall_from_installed_script() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR/c1" \ - --output-dir="$OUT_DIR/c1" \ - --component-name=rustc + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR/c1" \ + --output-dir="$OUT_DIR/c1" \ + --component-name=rustc try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR/c2" \ - --output-dir="$OUT_DIR/c2" \ - --component-name=cargo + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR/c2" \ + --output-dir="$OUT_DIR/c2" \ + --component-name=cargo try "$WORK_DIR/c1/package/install.sh" --prefix="$PREFIX_DIR" try "$WORK_DIR/c2/package/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/something-to-install" @@ -453,10 +453,10 @@ runtest uninstall_from_installed_script uninstall_from_installed_script_with_args_fails() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR/c1" \ - --output-dir="$OUT_DIR/c1" \ - --component-name=rustc + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR/c1" \ + --output-dir="$OUT_DIR/c1" \ + --component-name=rustc try "$WORK_DIR/c1/package/install.sh" --prefix="$PREFIX_DIR" expect_output_fail "uninstall.sh does not take any arguments" sh "$PREFIX_DIR/lib/packagelib/uninstall.sh" --prefix=foo } @@ -466,22 +466,22 @@ runtest uninstall_from_installed_script_with_args_fails combine_installers() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/something-to-install" try test -e "$PREFIX_DIR/dir-to-install/foo" @@ -502,28 +502,28 @@ runtest combine_installers combine_three_installers() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust-docs \ - --component-name=rust-docs + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust-docs \ + --component-name=rust-docs try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/something-to-install" try test -e "$PREFIX_DIR/dir-to-install/foo" @@ -546,25 +546,25 @@ runtest combine_three_installers combine_installers_with_overlay() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo mkdir -p "$WORK_DIR/overlay" touch "$WORK_DIR/overlay/README" try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" \ - --non-installed-overlay="$WORK_DIR/overlay" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" \ + --non-installed-overlay="$WORK_DIR/overlay" try test -e "$WORK_DIR/rust/README" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" try test ! -e "$PREFIX_DIR/README" @@ -573,23 +573,23 @@ runtest combine_installers_with_overlay combined_with_bulk_dirs() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc \ - --bulk-dirs=dir-to-install - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc \ + --bulk-dirs=dir-to-install + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/dir-to-install/foo" try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" @@ -599,25 +599,25 @@ runtest combined_with_bulk_dirs combine_install_with_separate_uninstall() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc \ - --rel-manifest-dir=rustlib - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo \ - --rel-manifest-dir=rustlib + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc \ + --rel-manifest-dir=rustlib + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo \ + --rel-manifest-dir=rustlib try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" \ - --rel-manifest-dir=rustlib + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" \ + --rel-manifest-dir=rustlib try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/something-to-install" try test -e "$PREFIX_DIR/dir-to-install/foo" @@ -639,28 +639,28 @@ runtest combine_install_with_separate_uninstall select_components_to_install() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust-docs \ - --component-name=rust-docs + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust-docs \ + --component-name=rust-docs try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" --components=rustc try test -e "$PREFIX_DIR/bin/program" try test ! -e "$PREFIX_DIR/bin/cargo" @@ -690,28 +690,28 @@ runtest select_components_to_install select_components_to_uninstall() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust-docs \ - --component-name=rust-docs + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust-docs \ + --component-name=rust-docs try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" --components=rustc try test ! -e "$PREFIX_DIR/bin/program" @@ -743,56 +743,56 @@ runtest select_components_to_uninstall invalid_component() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust-docs \ - --component-name=rust-docs + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust-docs \ + --component-name=rust-docs try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" expect_output_fail "unknown component" "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" --components=foo } runtest invalid_component without_components() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust-docs \ - --component-name=rust-docs + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust-docs \ + --component-name=rust-docs try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" --without=rust-docs try test -e "$PREFIX_DIR/bin/program" try test -e "$PREFIX_DIR/bin/cargo" @@ -815,28 +815,28 @@ runtest without_components # --without causes components to remain installed uninstall_without_components() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust-docs \ - --component-name=rust-docs + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust-docs \ + --component-name=rust-docs try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" --without=rust-docs try test ! -e "$PREFIX_DIR/bin/program" @@ -857,88 +857,88 @@ runtest uninstall_without_components without_any_components() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust-docs \ - --component-name=rust-docs + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust-docs \ + --component-name=rust-docs try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" expect_output_fail "no components selected for installation" \ - "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" --without=rust-docs,rustc,cargo + "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" --without=rust-docs,rustc,cargo } runtest without_any_components uninstall_without_any_components() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust-docs \ - --component-name=rust-docs + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust-docs \ + --component-name=rust-docs try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" expect_output_fail "no components selected for uninstallation" \ - "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" \ - --uninstall --without=rust-docs,rustc,cargo + "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" \ + --uninstall --without=rust-docs,rustc,cargo } runtest uninstall_without_any_components list_components() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust-docs \ - --component-name=rust-docs + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust-docs \ + --component-name=rust-docs try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" expect_output_ok "rustc" "$WORK_DIR/rust/install.sh" --list-components expect_output_ok "cargo" "$WORK_DIR/rust/install.sh" --list-components expect_output_ok "rust-docs" "$WORK_DIR/rust/install.sh" --list-components @@ -947,32 +947,32 @@ runtest list_components combined_remains() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rustc \ - --component-name=rustc - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image3" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=cargo \ - --component-name=cargo - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image4" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust-docs \ - --component-name=rust-docs + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rustc \ + --component-name=rustc + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image3" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=cargo \ + --component-name=cargo + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image4" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust-docs \ + --component-name=rust-docs try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" for component in rustc cargo rust-docs; do - # rustbuild wants the original extracted package intact too - try test -d "$WORK_DIR/$component/$component" - try test -d "$WORK_DIR/rust/$component" + # rustbuild wants the original extracted package intact too + try test -d "$WORK_DIR/$component/$component" + try test -d "$WORK_DIR/rust/$component" done } runtest combined_remains @@ -982,34 +982,34 @@ runtest combined_remains cannot_write_error() { # chmod doesn't work on windows if [ ! -n "${WINDOWS-}" ]; then - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" - chmod u-w "$PREFIX_DIR" - expect_fail "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" - chmod u+w "$PREFIX_DIR" + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" + chmod u-w "$PREFIX_DIR" + expect_fail "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" + chmod u+w "$PREFIX_DIR" fi } runtest cannot_write_error cannot_install_to_installer() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=my-package + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=my-package expect_output_fail "cannot install to same directory as installer" \ - "$WORK_DIR/my-package/install.sh" --prefix="$WORK_DIR/my-package" + "$WORK_DIR/my-package/install.sh" --prefix="$WORK_DIR/my-package" } runtest cannot_install_to_installer upgrade_from_future_installer_error() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --rel-manifest-dir=rustlib + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --rel-manifest-dir=rustlib try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" echo 100 > "$PREFIX_DIR/lib/rustlib/rust-installer-version" expect_fail "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" @@ -1018,9 +1018,9 @@ runtest upgrade_from_future_installer_error destdir() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" try "$WORK_DIR/package/install.sh" --destdir="$PREFIX_DIR/" --prefix=prefix try test -e "$PREFIX_DIR/prefix/bin/program" } @@ -1028,9 +1028,9 @@ runtest destdir destdir_no_trailing_slash() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" try "$WORK_DIR/package/install.sh" --destdir="$PREFIX_DIR" --prefix=prefix try test -e "$PREFIX_DIR/prefix/bin/program" } @@ -1055,7 +1055,7 @@ create_log() { try test -e "$PREFIX_DIR/lib/packagelib/install.log" local _log="$(cat "$PREFIX_DIR/lib/packagelib/install.log")" if [ -z "$_log" ]; then - fail "log is empty" + fail "log is empty" fi } runtest create_log @@ -1063,24 +1063,24 @@ runtest create_log leave_log_after_failure() { # chmod doesn't work on windows if [ ! -n "${WINDOWS-}" ]; then - try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" - mkdir -p "$PREFIX_DIR/lib/packagelib" - touch "$PREFIX_DIR/lib/packagelib/components" - chmod u-w "$PREFIX_DIR/lib/packagelib/components" - expect_fail "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" - chmod u+w "$PREFIX_DIR/lib/packagelib/components" - try test -e "$PREFIX_DIR/lib/packagelib/install.log" - local _log="$(cat "$PREFIX_DIR/lib/packagelib/install.log")" - if [ -z "$_log" ]; then - fail "log is empty" - fi - # script should tell user where the logs are - if ! grep -q "see logs at" "$PREFIX_DIR/lib/packagelib/install.log"; then - fail "missing log message" - fi + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" + mkdir -p "$PREFIX_DIR/lib/packagelib" + touch "$PREFIX_DIR/lib/packagelib/components" + chmod u-w "$PREFIX_DIR/lib/packagelib/components" + expect_fail "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" + chmod u+w "$PREFIX_DIR/lib/packagelib/components" + try test -e "$PREFIX_DIR/lib/packagelib/install.log" + local _log="$(cat "$PREFIX_DIR/lib/packagelib/install.log")" + if [ -z "$_log" ]; then + fail "log is empty" + fi + # script should tell user where the logs are + if ! grep -q "see logs at" "$PREFIX_DIR/lib/packagelib/install.log"; then + fail "missing log message" + fi fi } runtest leave_log_after_failure @@ -1088,9 +1088,9 @@ runtest leave_log_after_failure # https://github.com/rust-lang/rust-installer/issues/22 help() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" try "$WORK_DIR/package/install.sh" --help } runtest help @@ -1098,9 +1098,9 @@ runtest help # https://github.com/rust-lang/rust-installer/issues/31 CDPATH_does_not_destroy_things() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" cd "$WORK_DIR" || exit 1 export CDPATH="../$(basename $WORK_DIR)/foo" try sh "package/install.sh" --prefix="$PREFIX_DIR" @@ -1115,9 +1115,9 @@ runtest CDPATH_does_not_destroy_things docdir_default() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image-docdir1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" + --image-dir="$TEST_DIR/image-docdir1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" try test -e "$PREFIX_DIR/share/doc/rust/README" try test -e "$PREFIX_DIR/share/doc/rust/rustdocs.txt" @@ -1126,9 +1126,9 @@ runtest docdir_default docdir() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image-docdir1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" + --image-dir="$TEST_DIR/image-docdir1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" try mkdir "$WORK_DIR/docdir" try "$WORK_DIR/package/install.sh" --prefix="$PREFIX_DIR" --docdir="$WORK_DIR/docdir" try test -e "$WORK_DIR/docdir/README" @@ -1138,22 +1138,22 @@ runtest docdir docdir_combined() { try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image-docdir1" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ + --image-dir="$TEST_DIR/image-docdir1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ --package-name="rustc" \ --component-name="rustc" try sh "$S/gen-installer.sh" \ - --image-dir="$TEST_DIR/image-docdir2" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ + --image-dir="$TEST_DIR/image-docdir2" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ --package-name="cargo" \ --component-name="cargo" try sh "$S/combine-installers.sh" \ - --work-dir="$WORK_DIR" \ - --output-dir="$OUT_DIR" \ - --package-name=rust \ - --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" \ + --package-name=rust \ + --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz" try mkdir "$WORK_DIR/docdir" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" --docdir="$WORK_DIR/docdir" try test -e "$WORK_DIR/docdir/README" From 46d3fc78127798ea7e7c78bca31a8cb7586a7f94 Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 23 Jun 2023 12:48:59 +0300 Subject: [PATCH 07/22] fix bash long lines and replace TODO with FIXME --- src/tools/rust-installer/install-template.sh | 13 ++++++++----- src/tools/rust-installer/src/scripter.rs | 4 ++-- src/tools/rust-installer/test.sh | 12 ++++++++---- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/tools/rust-installer/install-template.sh b/src/tools/rust-installer/install-template.sh index 9246e5b7f5aed..6415644e0451d 100644 --- a/src/tools/rust-installer/install-template.sh +++ b/src/tools/rust-installer/install-template.sh @@ -468,7 +468,8 @@ uninstall_components() { verbose_msg "removing component manifest $_component_manifest" run rm "$_component_manifest" # This is a hard error because the installation is unrecoverable - critical_need_ok "failed to remove installed manifest for component '$_installed_component'" + local _err_cant_r_manifest="failed to remove installed manifest for component" + critical_need_ok "$_err_cant_r_manifest '$_installed_component'" # Update the installed component list local _modified_components="$(sed "/^$_installed_component\$/d" "$_md/components")" @@ -692,7 +693,9 @@ maybe_configure_ld() { fi if [ $? -ne 0 ] then - warn "failed to run ldconfig. this may happen when not installing as root. run with --verbose to see the error" + local _warn_s="failed to run ldconfig. this may happen when \ +not installing as root. run with --verbose to see the error" + warn "$_warn_s" fi fi } @@ -977,7 +980,9 @@ make_dir_recursive "$abs_libdir/$TEMPLATE_REL_MANIFEST_DIR" need_ok "failed to create $TEMPLATE_REL_MANIFEST_DIR" # Drop the version number into the manifest dir -write_to_file "$TEMPLATE_RUST_INSTALLER_VERSION" "$abs_libdir/$TEMPLATE_REL_MANIFEST_DIR/rust-installer-version" +write_to_file "$TEMPLATE_RUST_INSTALLER_VERSION" \ +"$abs_libdir/$TEMPLATE_REL_MANIFEST_DIR/rust-installer-version" + critical_need_ok "failed to write installer version" # Install the uninstaller @@ -992,5 +997,3 @@ maybe_configure_ld "$abs_libdir" echo echo " $TEMPLATE_SUCCESS_MESSAGE" echo - - diff --git a/src/tools/rust-installer/src/scripter.rs b/src/tools/rust-installer/src/scripter.rs index 3ce2d68c8bd17..30aed42e258b1 100644 --- a/src/tools/rust-installer/src/scripter.rs +++ b/src/tools/rust-installer/src/scripter.rs @@ -33,11 +33,11 @@ impl Scripter { /// Generates the actual installer script pub fn run(self) -> Result<()> { // Replace dashes in the success message with spaces (our arg handling botches spaces) - // TODO: still needed? Kept for compatibility for now. + // FIXME: still needed? Kept for compatibility for now. let product_name = self.product_name.replace('-', " "); // Replace dashes in the success message with spaces (our arg handling botches spaces) - // TODO: still needed? Kept for compatibility for now. + // FIXME: still needed? Kept for compatibility for now. let success_message = self.success_message.replace('-', " "); let script = TEMPLATE diff --git a/src/tools/rust-installer/test.sh b/src/tools/rust-installer/test.sh index d6b0492eea866..4f69bfc63e973 100755 --- a/src/tools/rust-installer/test.sh +++ b/src/tools/rust-installer/test.sh @@ -458,7 +458,8 @@ uninstall_from_installed_script_with_args_fails() { --output-dir="$OUT_DIR/c1" \ --component-name=rustc try "$WORK_DIR/c1/package/install.sh" --prefix="$PREFIX_DIR" - expect_output_fail "uninstall.sh does not take any arguments" sh "$PREFIX_DIR/lib/packagelib/uninstall.sh" --prefix=foo + expect_output_fail "uninstall.sh does not take any arguments" \ + sh "$PREFIX_DIR/lib/packagelib/uninstall.sh" --prefix=foo } runtest uninstall_from_installed_script_with_args_fails @@ -680,7 +681,8 @@ select_components_to_install() { try test -e "$PREFIX_DIR/bin/program" try test -e "$PREFIX_DIR/bin/cargo" try test ! -e "$PREFIX_DIR/baz" - try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" --components=rustc,cargo,rust-docs + try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" \ + --components=rustc,cargo,rust-docs try test ! -e "$PREFIX_DIR/bin/program" try test ! -e "$PREFIX_DIR/bin/cargo" try test ! -e "$PREFIX_DIR/baz" @@ -733,7 +735,8 @@ select_components_to_uninstall() { try test ! -e "$PREFIX_DIR/bin/cargo" try test -e "$PREFIX_DIR/baz" try "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" - try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" --components=rustc,cargo,rust-docs + try "$WORK_DIR/rust/install.sh --uninstall" --prefix="$PREFIX_DIR" \ + --components=rustc,cargo,rust-docs try test ! -e "$PREFIX_DIR/bin/program" try test ! -e "$PREFIX_DIR/bin/cargo" try test ! -e "$PREFIX_DIR/baz" @@ -765,7 +768,8 @@ invalid_component() { --output-dir="$OUT_DIR" \ --package-name=rust \ --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" - expect_output_fail "unknown component" "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" --components=foo + expect_output_fail "unknown component" "$WORK_DIR/rust/install.sh" --prefix="$PREFIX_DIR" \ + --components=foo } runtest invalid_component From a3bca31303fe9ea682cf0a9db79ec07fae8a0f41 Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 23 Jun 2023 12:54:34 +0300 Subject: [PATCH 08/22] tidy: exclude sh files from rust-installer tests from tidy bins check --- src/tools/tidy/src/bins.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/tools/tidy/src/bins.rs b/src/tools/tidy/src/bins.rs index 197e9a9965f7d..64ba79dc1857e 100644 --- a/src/tools/tidy/src/bins.rs +++ b/src/tools/tidy/src/bins.rs @@ -95,17 +95,41 @@ mod os_impl { return true; } + // FIXME: check when rust-installer test sh files will be removed, + // and then remove them from exclude list + const RI_EXCLUSION_LIST: &[&str] = &[ + "src/tools/rust-installer/test/image1/bin/program", + "src/tools/rust-installer/test/image1/bin/program2", + "src/tools/rust-installer/test/image1/bin/bad-bin", + "src/tools/rust-installer/test/image2/bin/oldprogram", + "src/tools/rust-installer/test/image3/bin/cargo", + ]; + + fn filter_rust_installer_no_so_bins(path: &Path) -> bool { + RI_EXCLUSION_LIST.iter().any(|p| path.ends_with(p)) + } + #[cfg(unix)] pub fn check(path: &Path, bad: &mut bool) { use std::ffi::OsStr; const ALLOWED: &[&str] = &["configure", "x"]; + for p in RI_EXCLUSION_LIST { + if !path.join(Path::new(p)).exists() { + tidy_error!(bad, "rust-installer test bins missed: {p}"); + } + } + // FIXME: we don't need to look at all binaries, only files that have been modified in this branch // (e.g. using `git ls-files`). walk_no_read( &[path], - |path, _is_dir| filter_dirs(path) || path.ends_with("src/etc"), + |path, _is_dir| { + filter_dirs(path) + || path.ends_with("src/etc") + || filter_rust_installer_no_so_bins(path) + }, &mut |entry| { let file = entry.path(); let extension = file.extension(); From ab914cf9f73f0004bad0ae6c086e804628a35e9f Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 23 Jun 2023 14:01:48 +0300 Subject: [PATCH 09/22] bootstrap: rust-installer no loger subtree, so allow running lints over it --- src/bootstrap/tool.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 126f0b1eb31a4..06c0317886299 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -289,7 +289,7 @@ bootstrap_tool!( Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true, allow_features = "test"; BuildManifest, "src/tools/build-manifest", "build-manifest"; RemoteTestClient, "src/tools/remote-test-client", "remote-test-client"; - RustInstaller, "src/tools/rust-installer", "rust-installer", is_external_tool = true; + RustInstaller, "src/tools/rust-installer", "rust-installer"; RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes"; ExpandYamlAnchors, "src/tools/expand-yaml-anchors", "expand-yaml-anchors"; LintDocs, "src/tools/lint-docs", "lint-docs"; From d5dbe867f62e3ec17b517f1f3d15dd75c895060b Mon Sep 17 00:00:00 2001 From: klensy Date: Tue, 4 Jul 2023 19:12:04 +0300 Subject: [PATCH 10/22] fix typo --- src/tools/rust-installer/src/scripter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-installer/src/scripter.rs b/src/tools/rust-installer/src/scripter.rs index 30aed42e258b1..ff65e818b09c8 100644 --- a/src/tools/rust-installer/src/scripter.rs +++ b/src/tools/rust-installer/src/scripter.rs @@ -32,7 +32,7 @@ actor! { impl Scripter { /// Generates the actual installer script pub fn run(self) -> Result<()> { - // Replace dashes in the success message with spaces (our arg handling botches spaces) + // Replace dashes in the product name with spaces (our arg handling botches spaces) // FIXME: still needed? Kept for compatibility for now. let product_name = self.product_name.replace('-', " "); From d2a1803d6fa30f102e2cce3c7f05da7a0d488eb1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 4 Jul 2023 18:06:41 +0000 Subject: [PATCH 11/22] Winnow specializing impls --- compiler/rustc_middle/src/ty/instance.rs | 4 ++-- .../src/solve/eval_ctxt/select.rs | 15 +++++++++++-- .../new-solver/winnow-specializing-impls.rs | 22 +++++++++++++++++++ 3 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 tests/ui/traits/new-solver/winnow-specializing-impls.rs diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index c0d591430f7fc..96750e4ab8534 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -410,8 +410,8 @@ impl<'tcx> Instance<'tcx> { ) -> Instance<'tcx> { match ty::Instance::resolve(tcx, param_env, def_id, substs) { Ok(Some(instance)) => instance, - _ => bug!( - "failed to resolve instance for {}", + instance => bug!( + "failed to resolve instance for {}: {instance:#?}", tcx.def_path_str_with_substs(def_id, substs) ), } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs index 466a03e21639c..18332d6811d56 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs @@ -52,7 +52,11 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> { let mut i = 0; while i < candidates.len() { let should_drop_i = (0..candidates.len()).filter(|&j| i != j).any(|j| { - candidate_should_be_dropped_in_favor_of(&candidates[i], &candidates[j]) + candidate_should_be_dropped_in_favor_of( + ecx.tcx(), + &candidates[i], + &candidates[j], + ) }); if should_drop_i { candidates.swap_remove(i); @@ -160,12 +164,19 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } fn candidate_should_be_dropped_in_favor_of<'tcx>( + tcx: TyCtxt<'tcx>, victim: &Candidate<'tcx>, other: &Candidate<'tcx>, ) -> bool { match (victim.source, other.source) { - (CandidateSource::ParamEnv(i), CandidateSource::ParamEnv(j)) => i >= j, + (CandidateSource::ParamEnv(victim_idx), CandidateSource::ParamEnv(other_idx)) => { + victim_idx >= other_idx + } (_, CandidateSource::ParamEnv(_)) => true, + (CandidateSource::Impl(victim_def_id), CandidateSource::Impl(other_def_id)) => { + tcx.specializes((other_def_id, victim_def_id)) + && other.result.value.certainty == Certainty::Yes + } _ => false, } } diff --git a/tests/ui/traits/new-solver/winnow-specializing-impls.rs b/tests/ui/traits/new-solver/winnow-specializing-impls.rs new file mode 100644 index 0000000000000..06f64de74030c --- /dev/null +++ b/tests/ui/traits/new-solver/winnow-specializing-impls.rs @@ -0,0 +1,22 @@ +// build-pass +// compile-flags: -Ztrait-solver=next + +// Tests that the specializing impl `<() as Foo>` holds during codegen. + +#![feature(min_specialization)] + +trait Foo { + fn bar(); +} + +impl Foo for T { + default fn bar() {} +} + +impl Foo for () { + fn bar() {} +} + +fn main() { + <() as Foo>::bar(); +} From d6b82ff7615dea4051212e22ca36d722017604f5 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 4 Jul 2023 07:00:09 +0000 Subject: [PATCH 12/22] Remove a redundant argument --- .../rustc_query_system/src/query/plumbing.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index b2bc33c7e0de0..4adb4eb7475be 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -126,18 +126,13 @@ where #[cold] #[inline(never)] -fn mk_cycle( - query: Q, - qcx: Qcx, - cycle_error: CycleError, - handler: HandleCycleError, -) -> Q::Value +fn mk_cycle(query: Q, qcx: Qcx, cycle_error: CycleError) -> Q::Value where Q: QueryConfig, Qcx: QueryContext, { let error = report_cycle(qcx.dep_context().sess(), &cycle_error); - handle_cycle_error(query, qcx, &cycle_error, error, handler) + handle_cycle_error(query, qcx, &cycle_error, error) } fn handle_cycle_error( @@ -145,14 +140,13 @@ fn handle_cycle_error( qcx: Qcx, cycle_error: &CycleError, mut error: DiagnosticBuilder<'_, ErrorGuaranteed>, - handler: HandleCycleError, ) -> Q::Value where Q: QueryConfig, Qcx: QueryContext, { use HandleCycleError::*; - match handler { + match query.handle_cycle_error() { Error => { error.emit(); query.value_from_cycle_error(*qcx.dep_context(), &cycle_error.cycle) @@ -277,7 +271,7 @@ where &qcx.current_query_job(), span, ); - (mk_cycle(query, qcx, error, query.handle_cycle_error()), None) + (mk_cycle(query, qcx, error), None) } #[inline(always)] @@ -314,7 +308,7 @@ where (v, Some(index)) } - Err(cycle) => (mk_cycle(query, qcx, cycle, query.handle_cycle_error()), None), + Err(cycle) => (mk_cycle(query, qcx, cycle), None), } } From 97d831d008601d02d22cbd1b21c4b45809eabe10 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 4 Jul 2023 07:56:54 +0000 Subject: [PATCH 13/22] Show which type was not specialized on query cycle misuse --- compiler/rustc_query_system/src/values.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_query_system/src/values.rs b/compiler/rustc_query_system/src/values.rs index b6e2cfa3dca5e..ce551078cc028 100644 --- a/compiler/rustc_query_system/src/values.rs +++ b/compiler/rustc_query_system/src/values.rs @@ -6,10 +6,13 @@ pub trait Value: Sized { } impl Value for T { - default fn from_cycle_error(tcx: Tcx, _: &[QueryInfo]) -> T { + default fn from_cycle_error(tcx: Tcx, cycle: &[QueryInfo]) -> T { tcx.sess().abort_if_errors(); // Ideally we would use `bug!` here. But bug! is only defined in rustc_middle, and it's // non-trivial to define it earlier. - panic!("Value::from_cycle_error called without errors"); + panic!( + "<{} as Value>::from_cycle_error called without errors: {cycle:#?}", + std::any::type_name::() + ); } } From 9cacfae3e901982558d19efabfc32f742436396f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 4 Jul 2023 08:28:35 +0000 Subject: [PATCH 14/22] Fix some tests to *only* test their main issue and not have secondary failures --- tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs | 2 +- tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr | 6 +++--- tests/ui/type-alias-impl-trait/inference-cycle.rs | 4 ++-- tests/ui/type-alias-impl-trait/inference-cycle.stderr | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs index 5fb7a9473d3df..43cd49d6ed715 100644 --- a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs @@ -4,7 +4,7 @@ // FIXME This should compile, but it currently doesn't mod m { - type Foo = impl std::fmt::Debug; + pub type Foo = impl std::fmt::Debug; //~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391] pub fn foo() -> Foo { diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr index 1e9a45aac79e9..6df59d98150c7 100644 --- a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr @@ -1,8 +1,8 @@ error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}` - --> $DIR/auto-trait-leakage3.rs:7:16 + --> $DIR/auto-trait-leakage3.rs:7:20 | -LL | type Foo = impl std::fmt::Debug; - | ^^^^^^^^^^^^^^^^^^^^ +LL | pub type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ | note: ...which requires type-checking `m::bar`... --> $DIR/auto-trait-leakage3.rs:15:9 diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.rs b/tests/ui/type-alias-impl-trait/inference-cycle.rs index 79caddf791320..01a4b9c0bb85b 100644 --- a/tests/ui/type-alias-impl-trait/inference-cycle.rs +++ b/tests/ui/type-alias-impl-trait/inference-cycle.rs @@ -2,7 +2,7 @@ #![allow(dead_code)] mod m { - type Foo = impl std::fmt::Debug; + pub type Foo = impl std::fmt::Debug; //~^ ERROR cycle detected // Cycle: error today, but it'd be nice if it eventually worked @@ -16,7 +16,7 @@ mod m { } fn baz() { - let f: Foo = 22_u32; + let f: Foo = (); } fn is_send(_: T) {} diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.stderr b/tests/ui/type-alias-impl-trait/inference-cycle.stderr index b9d646b927a6f..03ffe38ba2e2f 100644 --- a/tests/ui/type-alias-impl-trait/inference-cycle.stderr +++ b/tests/ui/type-alias-impl-trait/inference-cycle.stderr @@ -1,8 +1,8 @@ error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}` - --> $DIR/inference-cycle.rs:5:16 + --> $DIR/inference-cycle.rs:5:20 | -LL | type Foo = impl std::fmt::Debug; - | ^^^^^^^^^^^^^^^^^^^^ +LL | pub type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ | note: ...which requires type-checking `m::bar`... --> $DIR/inference-cycle.rs:15:9 From 66ae9998d5daf95d853343785e320b1d9af29955 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 4 Jul 2023 08:58:09 +0000 Subject: [PATCH 15/22] Remove redundant `delay_span_bug` --- .../src/traits/error_reporting/mod.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) 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 d5c13a9ccd144..e9d3ead5553f4 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1170,16 +1170,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } // Already reported in the query. - SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(_)) => { - // FIXME(eddyb) remove this once `ErrorGuaranteed` becomes a proof token. - self.tcx.sess.delay_span_bug(span, "`ErrorGuaranteed` without an error"); - return; - } + SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(_)) | // Already reported. - Overflow(OverflowError::Error(_)) => { - self.tcx.sess.delay_span_bug(span, "`OverflowError` has been reported"); - return; - } + Overflow(OverflowError::Error(_)) => return, + Overflow(_) => { bug!("overflow should be handled before the `report_selection_error` path"); } From 9e98feb84c36f369b7b0f163e82304ee799b1aef Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 4 Jul 2023 11:16:44 +0000 Subject: [PATCH 16/22] Add some extra information to opaque type cycle errors --- compiler/rustc_middle/src/traits/mod.rs | 4 + .../src/traits/error_reporting/mod.rs | 46 ++++++++- .../src/traits/select/confirmation.rs | 8 +- .../src/traits/select/mod.rs | 12 ++- tests/ui/generator/layout-error.rs | 1 + tests/ui/generator/layout-error.stderr | 20 +++- tests/ui/impl-trait/auto-trait-leak.rs | 6 +- tests/ui/impl-trait/auto-trait-leak.stderr | 91 +++++++++++++++++- tests/ui/impl-trait/issue-103181-2.rs | 2 + tests/ui/impl-trait/issue-103181-2.stderr | 57 ++++++++++- .../auto-trait-leakage3.rs | 2 + .../auto-trait-leakage3.stderr | 46 ++++++++- .../type-alias-impl-trait/inference-cycle.rs | 2 + .../inference-cycle.stderr | 46 ++++++++- .../ui/type-alias-impl-trait/reveal_local.rs | 6 +- .../type-alias-impl-trait/reveal_local.stderr | 96 ++++++++++++++++++- 16 files changed, 421 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 69d826bbe7adb..c7d2e4c22d293 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -588,6 +588,10 @@ pub enum SelectionError<'tcx> { /// Signaling that an error has already been emitted, to avoid /// multiple errors being shown. ErrorReporting, + /// Computing an opaque type's hidden type caused an error (e.g. a cycle error). + /// We can thus not know whether the hidden type implements an auto trait, so + /// we should not presume anything about it. + OpaqueTypeAutoTraitLeakageUnknown(DefId), } #[derive(Clone, Debug, TypeVisitable, Lift)] 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 e9d3ead5553f4..ec5782cc91655 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -30,7 +30,7 @@ use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::{InferOk, TypeTrace}; use rustc_middle::traits::select::OverflowError; use rustc_middle::traits::solve::Goal; -use rustc_middle::traits::SelectionOutputTypeParameterMismatch; +use rustc_middle::traits::{DefiningAnchor, SelectionOutputTypeParameterMismatch}; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; @@ -1152,6 +1152,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } + SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id) => self.report_opaque_type_auto_trait_leakage( + &obligation, + def_id, + ), + TraitNotObjectSafe(did) => { let violations = self.tcx.object_safety_violations(did); report_object_safety_error(self.tcx, span, did, violations) @@ -1465,6 +1470,12 @@ trait InferCtxtPrivExt<'tcx> { terr: TypeError<'tcx>, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>; + fn report_opaque_type_auto_trait_leakage( + &self, + obligation: &PredicateObligation<'tcx>, + def_id: DefId, + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>; + fn report_type_parameter_mismatch_error( &self, obligation: &PredicateObligation<'tcx>, @@ -3186,6 +3197,39 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) } + fn report_opaque_type_auto_trait_leakage( + &self, + obligation: &PredicateObligation<'tcx>, + def_id: DefId, + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + let name = match self.tcx.opaque_type_origin(def_id.expect_local()) { + hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) => { + format!("opaque type") + } + hir::OpaqueTyOrigin::TyAlias { .. } => { + format!("`{}`", self.tcx.def_path_debug_str(def_id)) + } + }; + let mut err = self.tcx.sess.struct_span_err( + obligation.cause.span, + format!("cannot check whether the hidden type of {name} satisfies auto traits"), + ); + err.span_note(self.tcx.def_span(def_id), "opaque type is declared here"); + match self.defining_use_anchor { + DefiningAnchor::Bubble | DefiningAnchor::Error => {} + DefiningAnchor::Bind(bind) => { + err.span_note( + self.tcx.def_ident_span(bind).unwrap_or_else(|| self.tcx.def_span(bind)), + "this item depends on auto traits of the hidden type, \ + but may also be registering the hidden type. \ + This is not supported right now. \ + You can try moving the opaque type and the item that actually registers a hidden type into a new submodule".to_string(), + ); + } + }; + err + } + fn report_type_parameter_mismatch_error( &self, obligation: &PredicateObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 24e895bc1841d..744c85ed51fff 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -67,7 +67,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } AutoImplCandidate => { - let data = self.confirm_auto_impl_candidate(obligation); + let data = self.confirm_auto_impl_candidate(obligation)?; ImplSource::Builtin(data) } @@ -376,12 +376,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_auto_impl_candidate( &mut self, obligation: &TraitObligation<'tcx>, - ) -> Vec> { + ) -> Result>, SelectionError<'tcx>> { debug!(?obligation, "confirm_auto_impl_candidate"); let self_ty = self.infcx.shallow_resolve(obligation.predicate.self_ty()); - let types = self.constituent_types_for_ty(self_ty); - self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types) + let types = self.constituent_types_for_ty(self_ty)?; + Ok(self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types)) } /// See `confirm_auto_impl_candidate`. diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index eb11163de4212..fece05cbb7def 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2294,8 +2294,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { fn constituent_types_for_ty( &self, t: ty::Binder<'tcx, Ty<'tcx>>, - ) -> ty::Binder<'tcx, Vec>> { - match *t.skip_binder().kind() { + ) -> Result>>, SelectionError<'tcx>> { + Ok(match *t.skip_binder().kind() { ty::Uint(_) | ty::Int(_) | ty::Bool @@ -2359,12 +2359,16 @@ impl<'tcx> SelectionContext<'_, 'tcx> { } ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => { + let ty = self.tcx().type_of(def_id); + if ty.skip_binder().references_error() { + return Err(SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id)); + } // We can resolve the `impl Trait` to its concrete type, // which enforces a DAG between the functions requiring // the auto trait bounds in question. - t.rebind(vec![self.tcx().type_of(def_id).subst(self.tcx(), substs)]) + t.rebind(vec![ty.subst(self.tcx(), substs)]) } - } + }) } fn collect_predicates_for_types( diff --git a/tests/ui/generator/layout-error.rs b/tests/ui/generator/layout-error.rs index 7c3d187409a2f..44cfc1d70ddc0 100644 --- a/tests/ui/generator/layout-error.rs +++ b/tests/ui/generator/layout-error.rs @@ -24,5 +24,6 @@ fn main() { type F = impl Future; // Check that statics are inhabited computes they layout. static POOL: Task = Task::new(); + //~^ ERROR: cannot check whether the hidden type of `layout_error[b009]::main::F::{opaque#0}` satisfies auto traits Task::spawn(&POOL, || cb()); } diff --git a/tests/ui/generator/layout-error.stderr b/tests/ui/generator/layout-error.stderr index b1a258f4f2ca7..ea3b25551c429 100644 --- a/tests/ui/generator/layout-error.stderr +++ b/tests/ui/generator/layout-error.stderr @@ -4,6 +4,24 @@ error[E0425]: cannot find value `Foo` in this scope LL | let a = Foo; | ^^^ not found in this scope -error: aborting due to previous error +error: cannot check whether the hidden type of `layout_error[b009]::main::F::{opaque#0}` satisfies auto traits + --> $DIR/layout-error.rs:26:18 + | +LL | static POOL: Task = Task::new(); + | ^^^^^^^ + | +note: opaque type is declared here + --> $DIR/layout-error.rs:24:14 + | +LL | type F = impl Future; + | ^^^^^^^^^^^ +note: required because it appears within the type `Task` + --> $DIR/layout-error.rs:9:12 + | +LL | pub struct Task(F); + | ^^^^ + = note: shared static variables must have a type that implements `Sync` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/impl-trait/auto-trait-leak.rs b/tests/ui/impl-trait/auto-trait-leak.rs index c2fbbf94fd666..d71c0987935ad 100644 --- a/tests/ui/impl-trait/auto-trait-leak.rs +++ b/tests/ui/impl-trait/auto-trait-leak.rs @@ -3,21 +3,23 @@ use std::rc::Rc; fn send(_: T) {} -fn main() { -} +fn main() {} // Cycles should work as the deferred obligations are // independently resolved and only require the concrete // return type, which can't depend on the obligation. fn cycle1() -> impl Clone { //~^ ERROR cycle detected + //~| ERROR cycle detected send(cycle2().clone()); + //~^ ERROR: cannot check whether the hidden type of opaque type satisfies auto traits Rc::new(Cell::new(5)) } fn cycle2() -> impl Clone { send(cycle1().clone()); + //~^ ERROR: cannot check whether the hidden type of opaque type satisfies auto traits Rc::new(String::from("foo")) } diff --git a/tests/ui/impl-trait/auto-trait-leak.stderr b/tests/ui/impl-trait/auto-trait-leak.stderr index c0c4cd5013e5f..92a9763bc9b57 100644 --- a/tests/ui/impl-trait/auto-trait-leak.stderr +++ b/tests/ui/impl-trait/auto-trait-leak.stderr @@ -1,5 +1,5 @@ error[E0391]: cycle detected when computing type of `cycle1::{opaque#0}` - --> $DIR/auto-trait-leak.rs:12:16 + --> $DIR/auto-trait-leak.rs:11:16 | LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^ @@ -11,12 +11,12 @@ LL | send(cycle2().clone()); | ^^^^ = note: ...which requires evaluating trait selection obligation `cycle2::{opaque#0}: core::marker::Send`... note: ...which requires computing type of `cycle2::{opaque#0}`... - --> $DIR/auto-trait-leak.rs:19:16 + --> $DIR/auto-trait-leak.rs:20:16 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^ note: ...which requires type-checking `cycle2`... - --> $DIR/auto-trait-leak.rs:20:5 + --> $DIR/auto-trait-leak.rs:21:5 | LL | send(cycle1().clone()); | ^^^^ @@ -34,6 +34,89 @@ LL | | Rc::new(String::from("foo")) LL | | } | |_^ -error: aborting due to previous error +error[E0391]: cycle detected when computing type of `cycle1::{opaque#0}` + --> $DIR/auto-trait-leak.rs:11:16 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^ + | +note: ...which requires type-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:14:5 + | +LL | send(cycle2().clone()); + | ^^^^ + = note: ...which requires evaluating trait selection obligation `cycle2::{opaque#0}: core::marker::Send`... +note: ...which requires computing type of `cycle2::{opaque#0}`... + --> $DIR/auto-trait-leak.rs:20:16 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^ +note: ...which requires type-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:20:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/auto-trait-leak.rs:1:1 + | +LL | / use std::cell::Cell; +LL | | use std::rc::Rc; +LL | | +LL | | fn send(_: T) {} +... | +LL | | Rc::new(String::from("foo")) +LL | | } + | |_^ + +error: cannot check whether the hidden type of opaque type satisfies auto traits + --> $DIR/auto-trait-leak.rs:21:10 + | +LL | send(cycle1().clone()); + | ---- ^^^^^^^^^^^^^^^^ + | | + | required by a bound introduced by this call + | +note: opaque type is declared here + --> $DIR/auto-trait-leak.rs:11:16 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^ +note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule + --> $DIR/auto-trait-leak.rs:20:4 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^ +note: required by a bound in `send` + --> $DIR/auto-trait-leak.rs:4:12 + | +LL | fn send(_: T) {} + | ^^^^ required by this bound in `send` + +error: cannot check whether the hidden type of opaque type satisfies auto traits + --> $DIR/auto-trait-leak.rs:14:10 + | +LL | send(cycle2().clone()); + | ---- ^^^^^^^^^^^^^^^^ + | | + | required by a bound introduced by this call + | +note: opaque type is declared here + --> $DIR/auto-trait-leak.rs:20:16 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^ +note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule + --> $DIR/auto-trait-leak.rs:11:4 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^ +note: required by a bound in `send` + --> $DIR/auto-trait-leak.rs:4:12 + | +LL | fn send(_: T) {} + | ^^^^ required by this bound in `send` + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/impl-trait/issue-103181-2.rs b/tests/ui/impl-trait/issue-103181-2.rs index b43ac45075e2b..34deb98beefe8 100644 --- a/tests/ui/impl-trait/issue-103181-2.rs +++ b/tests/ui/impl-trait/issue-103181-2.rs @@ -24,6 +24,8 @@ where B: Send, // <- a second bound { normalize(broken_fut(), ()); + //~^ ERROR: cannot check whether the hidden type of opaque type satisfies auto traits + //~| ERROR: cannot check whether the hidden type of opaque type satisfies auto traits } fn main() {} diff --git a/tests/ui/impl-trait/issue-103181-2.stderr b/tests/ui/impl-trait/issue-103181-2.stderr index 5eb2dd9184bec..cb5253ea6cd88 100644 --- a/tests/ui/impl-trait/issue-103181-2.stderr +++ b/tests/ui/impl-trait/issue-103181-2.stderr @@ -4,6 +4,61 @@ error[E0425]: cannot find value `ident_error` in this scope LL | ident_error; | ^^^^^^^^^^^ not found in this scope -error: aborting due to previous error +error: cannot check whether the hidden type of opaque type satisfies auto traits + --> $DIR/issue-103181-2.rs:26:15 + | +LL | normalize(broken_fut(), ()); + | --------- ^^^^^^^^^^^^ + | | + | required by a bound introduced by this call + | +note: opaque type is declared here + --> $DIR/issue-103181-2.rs:11:23 + | +LL | async fn broken_fut() { + | ^ +note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule + --> $DIR/issue-103181-2.rs:20:10 + | +LL | async fn iceice() + | ^^^^^^ +note: required for `impl Future` to implement `SendFuture` + --> $DIR/issue-103181-2.rs:7:17 + | +LL | impl SendFuture for Fut { + | ---- ^^^^^^^^^^ ^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `normalize` + --> $DIR/issue-103181-2.rs:18:19 + | +LL | fn normalize(_: Fut, _: Fut::Output) {} + | ^^^^^^^^^^ required by this bound in `normalize` + +error: cannot check whether the hidden type of opaque type satisfies auto traits + --> $DIR/issue-103181-2.rs:26:5 + | +LL | normalize(broken_fut(), ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: opaque type is declared here + --> $DIR/issue-103181-2.rs:11:23 + | +LL | async fn broken_fut() { + | ^ +note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule + --> $DIR/issue-103181-2.rs:20:10 + | +LL | async fn iceice() + | ^^^^^^ +note: required for `impl Future` to implement `SendFuture` + --> $DIR/issue-103181-2.rs:7:17 + | +LL | impl SendFuture for Fut { + | ---- ^^^^^^^^^^ ^^^ + | | + | unsatisfied trait bound introduced here + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs index 43cd49d6ed715..fd3f9c61420e9 100644 --- a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs @@ -6,6 +6,7 @@ mod m { pub type Foo = impl std::fmt::Debug; //~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391] + //~| ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391] pub fn foo() -> Foo { 22_u32 @@ -13,6 +14,7 @@ mod m { pub fn bar() { is_send(foo()); + //~^ ERROR: cannot check whether the hidden type of `auto_trait_leakage3[211d]::m::Foo::{opaque#0} } fn is_send(_: T) {} diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr index 6df59d98150c7..dd56c59bf5f23 100644 --- a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr @@ -5,7 +5,7 @@ LL | pub type Foo = impl std::fmt::Debug; | ^^^^^^^^^^^^^^^^^^^^ | note: ...which requires type-checking `m::bar`... - --> $DIR/auto-trait-leakage3.rs:15:9 + --> $DIR/auto-trait-leakage3.rs:16:9 | LL | is_send(foo()); | ^^^^^^^ @@ -17,6 +17,48 @@ note: cycle used when checking item types in module `m` LL | mod m { | ^^^^^ -error: aborting due to previous error +error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}` + --> $DIR/auto-trait-leakage3.rs:7:20 + | +LL | pub type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires type-checking `m::bar`... + --> $DIR/auto-trait-leakage3.rs:15:5 + | +LL | pub fn bar() { + | ^^^^^^^^^^^^ + = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in module `m` + --> $DIR/auto-trait-leakage3.rs:6:1 + | +LL | mod m { + | ^^^^^ + +error: cannot check whether the hidden type of `auto_trait_leakage3[211d]::m::Foo::{opaque#0}` satisfies auto traits + --> $DIR/auto-trait-leakage3.rs:16:17 + | +LL | is_send(foo()); + | ------- ^^^^^ + | | + | required by a bound introduced by this call + | +note: opaque type is declared here + --> $DIR/auto-trait-leakage3.rs:7:20 + | +LL | pub type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ +note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule + --> $DIR/auto-trait-leakage3.rs:15:12 + | +LL | pub fn bar() { + | ^^^ +note: required by a bound in `is_send` + --> $DIR/auto-trait-leakage3.rs:20:19 + | +LL | fn is_send(_: T) {} + | ^^^^ required by this bound in `is_send` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.rs b/tests/ui/type-alias-impl-trait/inference-cycle.rs index 01a4b9c0bb85b..093afc25249a7 100644 --- a/tests/ui/type-alias-impl-trait/inference-cycle.rs +++ b/tests/ui/type-alias-impl-trait/inference-cycle.rs @@ -4,6 +4,7 @@ mod m { pub type Foo = impl std::fmt::Debug; //~^ ERROR cycle detected + //~| ERROR cycle detected // Cycle: error today, but it'd be nice if it eventually worked @@ -13,6 +14,7 @@ mod m { pub fn bar() { is_send(foo()); // Today: error + //~^ ERROR: cannot check whether the hidden type of `inference_cycle[4ecc]::m::Foo::{opaque#0}` satisfies auto traits } fn baz() { diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.stderr b/tests/ui/type-alias-impl-trait/inference-cycle.stderr index 03ffe38ba2e2f..4d5f367476b7e 100644 --- a/tests/ui/type-alias-impl-trait/inference-cycle.stderr +++ b/tests/ui/type-alias-impl-trait/inference-cycle.stderr @@ -5,7 +5,7 @@ LL | pub type Foo = impl std::fmt::Debug; | ^^^^^^^^^^^^^^^^^^^^ | note: ...which requires type-checking `m::bar`... - --> $DIR/inference-cycle.rs:15:9 + --> $DIR/inference-cycle.rs:16:9 | LL | is_send(foo()); // Today: error | ^^^^^^^ @@ -17,6 +17,48 @@ note: cycle used when checking item types in module `m` LL | mod m { | ^^^^^ -error: aborting due to previous error +error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}` + --> $DIR/inference-cycle.rs:5:20 + | +LL | pub type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires type-checking `m::bar`... + --> $DIR/inference-cycle.rs:15:5 + | +LL | pub fn bar() { + | ^^^^^^^^^^^^ + = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in module `m` + --> $DIR/inference-cycle.rs:4:1 + | +LL | mod m { + | ^^^^^ + +error: cannot check whether the hidden type of `inference_cycle[4ecc]::m::Foo::{opaque#0}` satisfies auto traits + --> $DIR/inference-cycle.rs:16:17 + | +LL | is_send(foo()); // Today: error + | ------- ^^^^^ + | | + | required by a bound introduced by this call + | +note: opaque type is declared here + --> $DIR/inference-cycle.rs:5:20 + | +LL | pub type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ +note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule + --> $DIR/inference-cycle.rs:15:12 + | +LL | pub fn bar() { + | ^^^ +note: required by a bound in `is_send` + --> $DIR/inference-cycle.rs:24:19 + | +LL | fn is_send(_: T) {} + | ^^^^ required by this bound in `is_send` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/reveal_local.rs b/tests/ui/type-alias-impl-trait/reveal_local.rs index 7ecb553530106..75015e41c3da7 100644 --- a/tests/ui/type-alias-impl-trait/reveal_local.rs +++ b/tests/ui/type-alias-impl-trait/reveal_local.rs @@ -4,13 +4,16 @@ use std::fmt::Debug; type Foo = impl Debug; //~^ ERROR cycle detected +//~| ERROR cycle detected +//~| ERROR cycle detected -fn is_send() { } +fn is_send() {} fn not_good() { // Error: this function does not constrain `Foo` to any particular // hidden type, so it cannot rely on `Send` being true. is_send::(); + //~^ ERROR: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits } fn not_gooder() { @@ -20,6 +23,7 @@ fn not_gooder() { // while we could know this from the hidden type, it would // need extra roundabout logic to support it. is_send::(); + //~^ ERROR: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/reveal_local.stderr b/tests/ui/type-alias-impl-trait/reveal_local.stderr index 27fded3332921..202a87ecbb773 100644 --- a/tests/ui/type-alias-impl-trait/reveal_local.stderr +++ b/tests/ui/type-alias-impl-trait/reveal_local.stderr @@ -5,7 +5,7 @@ LL | type Foo = impl Debug; | ^^^^^^^^^^ | note: ...which requires type-checking `not_good`... - --> $DIR/reveal_local.rs:13:5 + --> $DIR/reveal_local.rs:15:5 | LL | is_send::(); | ^^^^^^^^^^^^^^ @@ -23,6 +23,98 @@ LL | | LL | | fn main() {} | |____________^ -error: aborting due to previous error +error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` + --> $DIR/reveal_local.rs:5:12 + | +LL | type Foo = impl Debug; + | ^^^^^^^^^^ + | +note: ...which requires type-checking `not_good`... + --> $DIR/reveal_local.rs:12:1 + | +LL | fn not_good() { + | ^^^^^^^^^^^^^ + = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/reveal_local.rs:1:1 + | +LL | / #![feature(type_alias_impl_trait)] +LL | | +LL | | use std::fmt::Debug; +LL | | +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits + --> $DIR/reveal_local.rs:15:15 + | +LL | is_send::(); + | ^^^ + | +note: opaque type is declared here + --> $DIR/reveal_local.rs:5:12 + | +LL | type Foo = impl Debug; + | ^^^^^^^^^^ +note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule + --> $DIR/reveal_local.rs:12:4 + | +LL | fn not_good() { + | ^^^^^^^^ +note: required by a bound in `is_send` + --> $DIR/reveal_local.rs:10:15 + | +LL | fn is_send() {} + | ^^^^ required by this bound in `is_send` + +error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` + --> $DIR/reveal_local.rs:5:12 + | +LL | type Foo = impl Debug; + | ^^^^^^^^^^ + | +note: ...which requires type-checking `not_gooder`... + --> $DIR/reveal_local.rs:19:1 + | +LL | fn not_gooder() { + | ^^^^^^^^^^^^^^^ + = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/reveal_local.rs:1:1 + | +LL | / #![feature(type_alias_impl_trait)] +LL | | +LL | | use std::fmt::Debug; +LL | | +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits + --> $DIR/reveal_local.rs:25:15 + | +LL | is_send::(); + | ^^^ + | +note: opaque type is declared here + --> $DIR/reveal_local.rs:5:12 + | +LL | type Foo = impl Debug; + | ^^^^^^^^^^ +note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule + --> $DIR/reveal_local.rs:19:4 + | +LL | fn not_gooder() { + | ^^^^^^^^^^ +note: required by a bound in `is_send` + --> $DIR/reveal_local.rs:10:15 + | +LL | fn is_send() {} + | ^^^^ required by this bound in `is_send` + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0391`. From 8ac3ffe83460bd77d69e2f199370403adbdac1fb Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 4 Jul 2023 11:46:01 +0100 Subject: [PATCH 17/22] move `ConstKind` to typeir and move inherent impls to `Const` --- compiler/rustc_middle/src/ty/consts.rs | 158 ++++++++++++- compiler/rustc_middle/src/ty/consts/kind.rs | 197 +--------------- compiler/rustc_middle/src/ty/context.rs | 8 + compiler/rustc_middle/src/ty/mod.rs | 4 +- .../rustc_middle/src/ty/structural_impls.rs | 18 -- compiler/rustc_middle/src/ty/sty.rs | 2 + compiler/rustc_type_ir/src/lib.rs | 10 +- .../rustc_type_ir/src/structural_impls.rs | 20 +- compiler/rustc_type_ir/src/sty.rs | 218 ++++++++++++++++++ 9 files changed, 413 insertions(+), 222 deletions(-) diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 44cdb9b1cd8fb..25b62d911d027 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -1,6 +1,6 @@ use crate::middle::resolve_bound_vars as rbv; -use crate::mir::interpret::LitToConstInput; -use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt}; +use crate::mir::interpret::{AllocId, ConstValue, LitToConstInput, Scalar}; +use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; use rustc_data_structures::intern::Interned; use rustc_error_messages::MultiSpan; use rustc_hir as hir; @@ -14,9 +14,13 @@ mod valtree; pub use int::*; pub use kind::*; +use rustc_span::ErrorGuaranteed; use rustc_span::DUMMY_SP; +use rustc_target::abi::Size; pub use valtree::*; +use super::sty::ConstKind; + /// Use this rather than `ConstData`, whenever possible. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] #[rustc_pass_by_value] @@ -32,6 +36,16 @@ pub struct ConstData<'tcx> { #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(ConstData<'_>, 40); +enum EvalMode { + Typeck, + Mir, +} + +enum EvalResult<'tcx> { + ValTree(ty::ValTree<'tcx>), + ConstVal(ConstValue<'tcx>), +} + impl<'tcx> Const<'tcx> { #[inline] pub fn ty(self) -> Ty<'tcx> { @@ -293,12 +307,12 @@ impl<'tcx> Const<'tcx> { assert_eq!(self.ty(), ty); let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; // if `ty` does not depend on generic parameters, use an empty param_env - self.kind().eval(tcx, param_env).try_to_bits(size) + self.eval(tcx, param_env).try_to_bits(size) } #[inline] pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { - self.kind().eval(tcx, param_env).try_to_bool() + self.eval(tcx, param_env).try_to_bool() } #[inline] @@ -307,14 +321,14 @@ impl<'tcx> Const<'tcx> { tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ) -> Option { - self.kind().eval(tcx, param_env).try_to_target_usize(tcx) + self.eval(tcx, param_env).try_to_target_usize(tcx) } #[inline] /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the /// unevaluated constant. pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Const<'tcx> { - if let Some(val) = self.kind().try_eval_for_typeck(tcx, param_env) { + if let Some(val) = self.try_eval_for_typeck(tcx, param_env) { match val { Ok(val) => ty::Const::new_value(tcx, val, self.ty()), Err(guar) => ty::Const::new_error(tcx, guar, self.ty()), @@ -339,6 +353,138 @@ impl<'tcx> Const<'tcx> { .unwrap_or_else(|| bug!("expected usize, got {:#?}", self)) } + #[inline] + /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary + /// return `None`. + // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged. + pub fn try_eval_for_mir( + self, + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + ) -> Option, ErrorGuaranteed>> { + match self.try_eval_inner(tcx, param_env, EvalMode::Mir) { + Some(Ok(EvalResult::ValTree(_))) => unreachable!(), + Some(Ok(EvalResult::ConstVal(v))) => Some(Ok(v)), + Some(Err(e)) => Some(Err(e)), + None => None, + } + } + + #[inline] + /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary + /// return `None`. + // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged. + pub fn try_eval_for_typeck( + self, + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + ) -> Option, ErrorGuaranteed>> { + match self.try_eval_inner(tcx, param_env, EvalMode::Typeck) { + Some(Ok(EvalResult::ValTree(v))) => Some(Ok(v)), + Some(Ok(EvalResult::ConstVal(_))) => unreachable!(), + Some(Err(e)) => Some(Err(e)), + None => None, + } + } + + #[inline] + fn try_eval_inner( + self, + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + eval_mode: EvalMode, + ) -> Option, ErrorGuaranteed>> { + assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}"); + if let ConstKind::Unevaluated(unevaluated) = self.kind() { + use crate::mir::interpret::ErrorHandled; + + // HACK(eddyb) this erases lifetimes even though `const_eval_resolve` + // also does later, but we want to do it before checking for + // inference variables. + // Note that we erase regions *before* calling `with_reveal_all_normalized`, + // so that we don't try to invoke this query with + // any region variables. + + // HACK(eddyb) when the query key would contain inference variables, + // attempt using identity substs and `ParamEnv` instead, that will succeed + // when the expression doesn't depend on any parameters. + // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that + // we can call `infcx.const_eval_resolve` which handles inference variables. + let param_env_and = if (param_env, unevaluated).has_non_region_infer() { + tcx.param_env(unevaluated.def).and(ty::UnevaluatedConst { + def: unevaluated.def, + substs: InternalSubsts::identity_for_item(tcx, unevaluated.def), + }) + } else { + tcx.erase_regions(param_env) + .with_reveal_all_normalized(tcx) + .and(tcx.erase_regions(unevaluated)) + }; + + // FIXME(eddyb) maybe the `const_eval_*` methods should take + // `ty::ParamEnvAnd` instead of having them separate. + let (param_env, unevaluated) = param_env_and.into_parts(); + // try to resolve e.g. associated constants to their definition on an impl, and then + // evaluate the const. + match eval_mode { + EvalMode::Typeck => { + match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, None) { + // NOTE(eddyb) `val` contains no lifetimes/types/consts, + // and we use the original type, so nothing from `substs` + // (which may be identity substs, see above), + // can leak through `val` into the const we return. + Ok(val) => Some(Ok(EvalResult::ValTree(val?))), + Err(ErrorHandled::TooGeneric) => None, + Err(ErrorHandled::Reported(e)) => Some(Err(e.into())), + } + } + EvalMode::Mir => { + match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) { + // NOTE(eddyb) `val` contains no lifetimes/types/consts, + // and we use the original type, so nothing from `substs` + // (which may be identity substs, see above), + // can leak through `val` into the const we return. + Ok(val) => Some(Ok(EvalResult::ConstVal(val))), + Err(ErrorHandled::TooGeneric) => None, + Err(ErrorHandled::Reported(e)) => Some(Err(e.into())), + } + } + } + } else { + None + } + } + + #[inline] + pub fn try_to_value(self) -> Option> { + if let ConstKind::Value(val) = self.kind() { Some(val) } else { None } + } + + #[inline] + pub fn try_to_scalar(self) -> Option> { + self.try_to_value()?.try_to_scalar() + } + + #[inline] + pub fn try_to_scalar_int(self) -> Option { + self.try_to_value()?.try_to_scalar_int() + } + + #[inline] + pub fn try_to_bits(self, size: Size) -> Option { + self.try_to_scalar_int()?.to_bits(size).ok() + } + + #[inline] + pub fn try_to_bool(self) -> Option { + self.try_to_scalar_int()?.try_into().ok() + } + + #[inline] + pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option { + self.try_to_value()?.try_to_target_usize(tcx) + } + pub fn is_ct_infer(self) -> bool { matches!(self.kind(), ty::ConstKind::Infer(_)) } diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 1dd4f8a243741..61b02e058e419 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -1,17 +1,12 @@ use super::Const; use crate::mir; -use crate::mir::interpret::{AllocId, ConstValue, Scalar}; use crate::ty::abstract_const::CastKind; -use crate::ty::subst::{InternalSubsts, SubstsRef}; -use crate::ty::ParamEnv; -use crate::ty::{self, List, Ty, TyCtxt, TypeVisitableExt}; +use crate::ty::sty::ConstKind; +use crate::ty::subst::SubstsRef; +use crate::ty::{self, List, Ty}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; -use rustc_target::abi::Size; - -use super::ScalarInt; /// An unevaluated (potentially generic) constant used in the type-system. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] @@ -41,39 +36,6 @@ impl<'tcx> UnevaluatedConst<'tcx> { } } -/// Represents a constant in Rust. -#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)] -#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)] -#[derive(derive_more::From)] -pub enum ConstKind<'tcx> { - /// A const generic parameter. - Param(ty::ParamConst), - - /// Infer the value of the const. - Infer(InferConst<'tcx>), - - /// Bound const variable, used only when preparing a trait query. - Bound(ty::DebruijnIndex, ty::BoundVar), - - /// A placeholder const - universally quantified higher-ranked const. - Placeholder(ty::PlaceholderConst<'tcx>), - - /// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other - /// variants when the code is monomorphic enough for that. - Unevaluated(UnevaluatedConst<'tcx>), - - /// Used to hold computed value. - Value(ty::ValTree<'tcx>), - - /// A placeholder for a const which could not be computed; this is - /// propagated to avoid useless error messages. - #[from(ignore)] - Error(ErrorGuaranteed), - - /// Expr which contains an expression which has partially evaluated items. - Expr(Expr<'tcx>), -} - impl<'tcx> From> for ConstKind<'tcx> { fn from(const_vid: ty::ConstVid<'tcx>) -> Self { InferConst::Var(const_vid).into() @@ -95,38 +57,6 @@ static_assert_size!(Expr<'_>, 24); #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(ConstKind<'_>, 32); -impl<'tcx> ConstKind<'tcx> { - #[inline] - pub fn try_to_value(self) -> Option> { - if let ConstKind::Value(val) = self { Some(val) } else { None } - } - - #[inline] - pub fn try_to_scalar(self) -> Option> { - self.try_to_value()?.try_to_scalar() - } - - #[inline] - pub fn try_to_scalar_int(self) -> Option { - self.try_to_value()?.try_to_scalar_int() - } - - #[inline] - pub fn try_to_bits(self, size: Size) -> Option { - self.try_to_scalar_int()?.to_bits(size).ok() - } - - #[inline] - pub fn try_to_bool(self) -> Option { - self.try_to_scalar_int()?.try_into().ok() - } - - #[inline] - pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option { - self.try_to_value()?.try_to_target_usize(tcx) - } -} - /// An inference variable for a const, for use in const generics. #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)] pub enum InferConst<'tcx> { @@ -144,124 +74,3 @@ impl HashStable for InferConst<'_> { } } } - -enum EvalMode { - Typeck, - Mir, -} - -enum EvalResult<'tcx> { - ValTree(ty::ValTree<'tcx>), - ConstVal(ConstValue<'tcx>), -} - -impl<'tcx> ConstKind<'tcx> { - #[inline] - /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the - /// unevaluated constant. - pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self { - self.try_eval_for_typeck(tcx, param_env).and_then(Result::ok).map_or(self, ConstKind::Value) - } - - #[inline] - /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary - /// return `None`. - // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged. - pub fn try_eval_for_mir( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - ) -> Option, ErrorGuaranteed>> { - match self.try_eval_inner(tcx, param_env, EvalMode::Mir) { - Some(Ok(EvalResult::ValTree(_))) => unreachable!(), - Some(Ok(EvalResult::ConstVal(v))) => Some(Ok(v)), - Some(Err(e)) => Some(Err(e)), - None => None, - } - } - - #[inline] - /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary - /// return `None`. - // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged. - pub fn try_eval_for_typeck( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - ) -> Option, ErrorGuaranteed>> { - match self.try_eval_inner(tcx, param_env, EvalMode::Typeck) { - Some(Ok(EvalResult::ValTree(v))) => Some(Ok(v)), - Some(Ok(EvalResult::ConstVal(_))) => unreachable!(), - Some(Err(e)) => Some(Err(e)), - None => None, - } - } - - #[inline] - fn try_eval_inner( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - eval_mode: EvalMode, - ) -> Option, ErrorGuaranteed>> { - assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}"); - if let ConstKind::Unevaluated(unevaluated) = self { - use crate::mir::interpret::ErrorHandled; - - // HACK(eddyb) this erases lifetimes even though `const_eval_resolve` - // also does later, but we want to do it before checking for - // inference variables. - // Note that we erase regions *before* calling `with_reveal_all_normalized`, - // so that we don't try to invoke this query with - // any region variables. - - // HACK(eddyb) when the query key would contain inference variables, - // attempt using identity substs and `ParamEnv` instead, that will succeed - // when the expression doesn't depend on any parameters. - // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that - // we can call `infcx.const_eval_resolve` which handles inference variables. - let param_env_and = if (param_env, unevaluated).has_non_region_infer() { - tcx.param_env(unevaluated.def).and(ty::UnevaluatedConst { - def: unevaluated.def, - substs: InternalSubsts::identity_for_item(tcx, unevaluated.def), - }) - } else { - tcx.erase_regions(param_env) - .with_reveal_all_normalized(tcx) - .and(tcx.erase_regions(unevaluated)) - }; - - // FIXME(eddyb) maybe the `const_eval_*` methods should take - // `ty::ParamEnvAnd` instead of having them separate. - let (param_env, unevaluated) = param_env_and.into_parts(); - // try to resolve e.g. associated constants to their definition on an impl, and then - // evaluate the const. - match eval_mode { - EvalMode::Typeck => { - match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, None) { - // NOTE(eddyb) `val` contains no lifetimes/types/consts, - // and we use the original type, so nothing from `substs` - // (which may be identity substs, see above), - // can leak through `val` into the const we return. - Ok(val) => Some(Ok(EvalResult::ValTree(val?))), - Err(ErrorHandled::TooGeneric) => None, - Err(ErrorHandled::Reported(e)) => Some(Err(e.into())), - } - } - EvalMode::Mir => { - match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) { - // NOTE(eddyb) `val` contains no lifetimes/types/consts, - // and we use the original type, so nothing from `substs` - // (which may be identity substs, see above), - // can leak through `val` into the const we return. - Ok(val) => Some(Ok(EvalResult::ConstVal(val))), - Err(ErrorHandled::TooGeneric) => None, - Err(ErrorHandled::Reported(e)) => Some(Err(e.into())), - } - } - } - } else { - None - } - } -} diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index e50331bc461e9..83e0c849c5597 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -108,6 +108,14 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type PredicateKind = ty::PredicateKind<'tcx>; type AllocId = crate::mir::interpret::AllocId; + type InferConst = ty::InferConst<'tcx>; + type AliasConst = ty::UnevaluatedConst<'tcx>; + type ParamConst = ty::ParamConst; + type BoundConst = ty::BoundVar; + type PlaceholderConst = ty::PlaceholderConst<'tcx>; + type ValueConst = ty::ValTree<'tcx>; + type ExprConst = ty::Expr<'tcx>; + type EarlyBoundRegion = ty::EarlyBoundRegion; type BoundRegion = ty::BoundRegion; type FreeRegion = ty::FreeRegion; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 48388be2f4643..b443708b22c71 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -81,7 +81,7 @@ pub use self::closure::{ CAPTURE_STRUCT_LOCAL, }; pub use self::consts::{ - Const, ConstData, ConstInt, ConstKind, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree, + Const, ConstData, ConstInt, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree, }; pub use self::context::{ tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, @@ -93,7 +93,7 @@ pub use self::rvalue_scopes::RvalueScopes; pub use self::sty::BoundRegionKind::*; pub use self::sty::{ AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, - BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid, + BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstKind, ConstVid, EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts, InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate, diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 15fb94fe0901c..fa72483271820 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -241,24 +241,6 @@ impl<'tcx> fmt::Debug for ty::Const<'tcx> { } } -impl<'tcx> fmt::Debug for ty::ConstKind<'tcx> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - use ty::ConstKind::*; - match self { - Param(param) => write!(f, "{param:?}"), - Infer(var) => write!(f, "{var:?}"), - Bound(debruijn, var) => rustc_type_ir::debug_bound_var(f, *debruijn, *var), - Placeholder(placeholder) => write!(f, "{placeholder:?}"), - Unevaluated(uv) => { - f.debug_tuple("Unevaluated").field(&uv.substs).field(&uv.def).finish() - } - Value(valtree) => write!(f, "{valtree:?}"), - Error(_) => write!(f, "{{const error}}"), - Expr(expr) => write!(f, "{expr:?}"), - } - } -} - impl fmt::Debug for ty::BoundTy { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.kind { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index bb6d49e177357..9046570699e93 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -33,6 +33,7 @@ use std::ops::{ControlFlow, Deref, Range}; use ty::util::IntTypeExt; use rustc_type_ir::sty::TyKind::*; +use rustc_type_ir::ConstKind as IrConstKind; use rustc_type_ir::RegionKind as IrRegionKind; use rustc_type_ir::TyKind as IrTyKind; @@ -40,6 +41,7 @@ use rustc_type_ir::TyKind as IrTyKind; #[rustc_diagnostic_item = "TyKind"] pub type TyKind<'tcx> = IrTyKind>; pub type RegionKind<'tcx> = IrRegionKind>; +pub type ConstKind<'tcx> = IrConstKind>; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index ae16fbb162e5c..878a6b784ed6c 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -57,11 +57,19 @@ pub trait Interner: Sized { type ParamTy: Clone + Debug + Hash + Ord; type BoundTy: Clone + Debug + Hash + Ord; type PlaceholderType: Clone + Debug + Hash + Ord; - type InferTy: Clone + Debug + Hash + Ord; type ErrorGuaranteed: Clone + Debug + Hash + Ord; type PredicateKind: Clone + Debug + Hash + PartialEq + Eq; type AllocId: Clone + Debug + Hash + Ord; + type InferConst: Clone + Debug + Hash + Ord; + type AliasConst: Clone + Debug + Hash + Ord; + type PlaceholderConst: Clone + Debug + Hash + Ord; + type ParamConst: Clone + Debug + Hash + Ord; + type BoundConst: Clone + Debug + Hash + Ord; + type InferTy: Clone + Debug + Hash + Ord; + type ValueConst: Clone + Debug + Hash + Ord; + type ExprConst: Clone + Debug + Hash + Ord; + type EarlyBoundRegion: Clone + Debug + Hash + Ord; type BoundRegion: Clone + Debug + Hash + Ord; type FreeRegion: Clone + Debug + Hash + Ord; diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs index 553d7f31b2d19..1e42175f6e3e8 100644 --- a/compiler/rustc_type_ir/src/structural_impls.rs +++ b/compiler/rustc_type_ir/src/structural_impls.rs @@ -4,7 +4,7 @@ use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::visit::{TypeVisitable, TypeVisitor}; -use crate::{FloatTy, IntTy, Interner, UintTy}; +use crate::{ConstKind, FloatTy, IntTy, Interner, UintTy}; use rustc_data_structures::functor::IdFunctor; use rustc_data_structures::sync::Lrc; use rustc_index::{Idx, IndexVec}; @@ -182,3 +182,21 @@ impl fmt::Debug for FloatTy { write!(f, "{}", self.name_str()) } } + +impl fmt::Debug for ConstKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + use ConstKind::*; + match self { + Param(param) => write!(f, "{param:?}"), + Infer(var) => write!(f, "{var:?}"), + Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var.clone()), + Placeholder(placeholder) => write!(f, "{placeholder:?}"), + Unevaluated(uv) => { + write!(f, "{uv:?}") + } + Value(valtree) => write!(f, "{valtree:?}"), + Error(_) => write!(f, "{{const error}}"), + Expr(expr) => write!(f, "{expr:?}"), + } + } +} diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index f621673f1d6f1..b696f9b9b5915 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -876,6 +876,224 @@ where } } +/// Represents a constant in Rust. +// #[derive(derive_more::From)] +pub enum ConstKind { + /// A const generic parameter. + Param(I::ParamConst), + + /// Infer the value of the const. + Infer(I::InferConst), + + /// Bound const variable, used only when preparing a trait query. + Bound(DebruijnIndex, I::BoundConst), + + /// A placeholder const - universally quantified higher-ranked const. + Placeholder(I::PlaceholderConst), + + /// An unnormalized const item such as an anon const or assoc const or free const item. + /// Right now anything other than anon consts does not actually work properly but this + /// should + Unevaluated(I::AliasConst), + + /// Used to hold computed value. + Value(I::ValueConst), + + /// A placeholder for a const which could not be computed; this is + /// propagated to avoid useless error messages. + Error(I::ErrorGuaranteed), + + /// Unevaluated non-const-item, used by `feature(generic_const_exprs)` to represent + /// const arguments such as `N + 1` or `foo(N)` + Expr(I::ExprConst), +} + +const fn const_kind_discriminant(value: &ConstKind) -> usize { + match value { + ConstKind::Param(_) => 0, + ConstKind::Infer(_) => 1, + ConstKind::Bound(_, _) => 2, + ConstKind::Placeholder(_) => 3, + ConstKind::Unevaluated(_) => 4, + ConstKind::Value(_) => 5, + ConstKind::Error(_) => 6, + ConstKind::Expr(_) => 7, + } +} + +impl hash::Hash for ConstKind { + fn hash(&self, state: &mut H) { + const_kind_discriminant(self).hash(state); + match self { + ConstKind::Param(p) => p.hash(state), + ConstKind::Infer(i) => i.hash(state), + ConstKind::Bound(d, b) => { + d.hash(state); + b.hash(state); + } + ConstKind::Placeholder(p) => p.hash(state), + ConstKind::Unevaluated(u) => u.hash(state), + ConstKind::Value(v) => v.hash(state), + ConstKind::Error(e) => e.hash(state), + ConstKind::Expr(e) => e.hash(state), + } + } +} + +impl HashStable for ConstKind +where + I::ParamConst: HashStable, + I::InferConst: HashStable, + I::BoundConst: HashStable, + I::PlaceholderConst: HashStable, + I::AliasConst: HashStable, + I::ValueConst: HashStable, + I::ErrorGuaranteed: HashStable, + I::ExprConst: HashStable, +{ + fn hash_stable( + &self, + hcx: &mut CTX, + hasher: &mut rustc_data_structures::stable_hasher::StableHasher, + ) { + const_kind_discriminant(self).hash_stable(hcx, hasher); + match self { + ConstKind::Param(p) => p.hash_stable(hcx, hasher), + ConstKind::Infer(i) => i.hash_stable(hcx, hasher), + ConstKind::Bound(d, b) => { + d.hash_stable(hcx, hasher); + b.hash_stable(hcx, hasher); + } + ConstKind::Placeholder(p) => p.hash_stable(hcx, hasher), + ConstKind::Unevaluated(u) => u.hash_stable(hcx, hasher), + ConstKind::Value(v) => v.hash_stable(hcx, hasher), + ConstKind::Error(e) => e.hash_stable(hcx, hasher), + ConstKind::Expr(e) => e.hash_stable(hcx, hasher), + } + } +} + +impl> Decodable for ConstKind +where + I::ParamConst: Decodable, + I::InferConst: Decodable, + I::BoundConst: Decodable, + I::PlaceholderConst: Decodable, + I::AliasConst: Decodable, + I::ValueConst: Decodable, + I::ErrorGuaranteed: Decodable, + I::ExprConst: Decodable, +{ + fn decode(d: &mut D) -> Self { + match Decoder::read_usize(d) { + 0 => ConstKind::Param(Decodable::decode(d)), + 1 => ConstKind::Infer(Decodable::decode(d)), + 2 => ConstKind::Bound(Decodable::decode(d), Decodable::decode(d)), + 3 => ConstKind::Placeholder(Decodable::decode(d)), + 4 => ConstKind::Unevaluated(Decodable::decode(d)), + 5 => ConstKind::Value(Decodable::decode(d)), + 6 => ConstKind::Error(Decodable::decode(d)), + 7 => ConstKind::Expr(Decodable::decode(d)), + _ => panic!( + "{}", + format!( + "invalid enum variant tag while decoding `{}`, expected 0..{}", + "ConstKind", 8, + ) + ), + } + } +} + +impl> Encodable for ConstKind +where + I::ParamConst: Encodable, + I::InferConst: Encodable, + I::BoundConst: Encodable, + I::PlaceholderConst: Encodable, + I::AliasConst: Encodable, + I::ValueConst: Encodable, + I::ErrorGuaranteed: Encodable, + I::ExprConst: Encodable, +{ + fn encode(&self, e: &mut E) { + let disc = const_kind_discriminant(self); + match self { + ConstKind::Param(p) => e.emit_enum_variant(disc, |e| p.encode(e)), + ConstKind::Infer(i) => e.emit_enum_variant(disc, |e| i.encode(e)), + ConstKind::Bound(d, b) => e.emit_enum_variant(disc, |e| { + d.encode(e); + b.encode(e); + }), + ConstKind::Placeholder(p) => e.emit_enum_variant(disc, |e| p.encode(e)), + ConstKind::Unevaluated(u) => e.emit_enum_variant(disc, |e| u.encode(e)), + ConstKind::Value(v) => e.emit_enum_variant(disc, |e| v.encode(e)), + ConstKind::Error(er) => e.emit_enum_variant(disc, |e| er.encode(e)), + ConstKind::Expr(ex) => e.emit_enum_variant(disc, |e| ex.encode(e)), + } + } +} + +impl PartialOrd for ConstKind { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for ConstKind { + fn cmp(&self, other: &Self) -> Ordering { + const_kind_discriminant(self) + .cmp(&const_kind_discriminant(other)) + .then_with(|| match (self, other) { + (ConstKind::Param(p1), ConstKind::Param(p2)) => p1.cmp(p2), + (ConstKind::Infer(i1), ConstKind::Infer(i2)) => i1.cmp(i2), + (ConstKind::Bound(d1, b1), ConstKind::Bound(d2, b2)) => d1.cmp(d2).then_with(|| b1.cmp(b2)), + (ConstKind::Placeholder(p1), ConstKind::Placeholder(p2)) => p1.cmp(p2), + (ConstKind::Unevaluated(u1), ConstKind::Unevaluated(u2)) => u1.cmp(u2), + (ConstKind::Value(v1), ConstKind::Value(v2)) => v1.cmp(v2), + (ConstKind::Error(e1), ConstKind::Error(e2)) => e1.cmp(e2), + (ConstKind::Expr(e1), ConstKind::Expr(e2)) => e1.cmp(e2), + _ => { + debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}"); + Ordering::Equal + } + }) + } +} + +impl PartialEq for ConstKind { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Self::Param(l0), Self::Param(r0)) => l0 == r0, + (Self::Infer(l0), Self::Infer(r0)) => l0 == r0, + (Self::Bound(l0, l1), Self::Bound(r0, r1)) => l0 == r0 && l1 == r1, + (Self::Placeholder(l0), Self::Placeholder(r0)) => l0 == r0, + (Self::Unevaluated(l0), Self::Unevaluated(r0)) => l0 == r0, + (Self::Value(l0), Self::Value(r0)) => l0 == r0, + (Self::Error(l0), Self::Error(r0)) => l0 == r0, + (Self::Expr(l0), Self::Expr(r0)) => l0 == r0, + _ => false, + } + } +} + +impl Eq for ConstKind {} + +impl Clone for ConstKind { + fn clone(&self) -> Self { + match self { + Self::Param(arg0) => Self::Param(arg0.clone()), + Self::Infer(arg0) => Self::Infer(arg0.clone()), + Self::Bound(arg0, arg1) => Self::Bound(arg0.clone(), arg1.clone()), + Self::Placeholder(arg0) => Self::Placeholder(arg0.clone()), + Self::Unevaluated(arg0) => Self::Unevaluated(arg0.clone()), + Self::Value(arg0) => Self::Value(arg0.clone()), + Self::Error(arg0) => Self::Error(arg0.clone()), + Self::Expr(arg0) => Self::Expr(arg0.clone()), + } + } +} + /// Representation of regions. Note that the NLL checker uses a distinct /// representation of regions. For this reason, it internally replaces all the /// regions with inference variables -- the index of the variable is then used From 62174bfe7255f2e238b44923ad6d6abde630f1ab Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 4 Jul 2023 15:41:45 +0100 Subject: [PATCH 18/22] Deal with fallout --- compiler/rustc_codegen_cranelift/src/base.rs | 1 - compiler/rustc_middle/src/mir/mod.rs | 4 +-- compiler/rustc_middle/src/ty/consts.rs | 2 +- compiler/rustc_middle/src/ty/consts/kind.rs | 9 +----- .../ty/inhabitedness/inhabited_predicate.rs | 2 +- .../rustc_middle/src/ty/inhabitedness/mod.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 4 +++ .../rustc_middle/src/ty/structural_impls.rs | 28 +++++++++++++++++-- compiler/rustc_middle/src/ty/util.rs | 2 +- compiler/rustc_symbol_mangling/src/legacy.rs | 2 +- .../src/typeid/typeid_itanium_cxx_abi.rs | 6 ++-- compiler/rustc_symbol_mangling/src/v0.rs | 2 +- .../error_reporting/on_unimplemented.rs | 2 +- .../src/traits/fulfill.rs | 2 +- .../src/traits/select/mod.rs | 2 +- src/tools/clippy/clippy_utils/src/consts.rs | 4 +-- .../mir-opt/issue_99325.main.built.after.mir | 2 +- 17 files changed, 47 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index ce10780f9de12..5f78cce50e695 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -706,7 +706,6 @@ fn codegen_stmt<'tcx>( let times = fx .monomorphize(times) .eval(fx.tcx, ParamEnv::reveal_all()) - .kind() .try_to_bits(fx.tcx.data_layout.pointer_size) .unwrap(); if operand.layout().size.bytes() == 0 { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 124b569204807..49563d0eee0f3 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2329,7 +2329,7 @@ impl<'tcx> ConstantKind<'tcx> { pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self { match self { Self::Ty(c) => { - if let Some(val) = c.kind().try_eval_for_mir(tcx, param_env) { + if let Some(val) = c.try_eval_for_mir(tcx, param_env) { match val { Ok(val) => Self::Val(val, c.ty()), Err(guar) => Self::Ty(ty::Const::new_error(tcx, guar, self.ty())), @@ -2867,7 +2867,7 @@ fn pretty_print_const_value<'tcx>( } } (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => { - let n = n.kind().try_to_bits(tcx.data_layout.pointer_size).unwrap(); + let n = n.try_to_bits(tcx.data_layout.pointer_size).unwrap(); // cast is ok because we already checked for pointer size (32 or 64 bit) above let range = AllocRange { start: offset, size: Size::from_bytes(n) }; let byte_str = alloc.inner().get_bytes_strip_provenance(&tcx, range).unwrap(); diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 25b62d911d027..78943cb0ddb60 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -54,7 +54,7 @@ impl<'tcx> Const<'tcx> { #[inline] pub fn kind(self) -> ConstKind<'tcx> { - self.0.kind + self.0.kind.clone() } #[inline] diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 61b02e058e419..a6bf749111858 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -1,7 +1,6 @@ use super::Const; use crate::mir; use crate::ty::abstract_const::CastKind; -use crate::ty::sty::ConstKind; use crate::ty::subst::SubstsRef; use crate::ty::{self, List, Ty}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -36,12 +35,6 @@ impl<'tcx> UnevaluatedConst<'tcx> { } } -impl<'tcx> From> for ConstKind<'tcx> { - fn from(const_vid: ty::ConstVid<'tcx>) -> Self { - InferConst::Var(const_vid).into() - } -} - #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] #[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)] pub enum Expr<'tcx> { @@ -55,7 +48,7 @@ pub enum Expr<'tcx> { static_assert_size!(Expr<'_>, 24); #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(ConstKind<'_>, 32); +static_assert_size!(super::ConstKind<'_>, 32); /// An inference variable for a const, for use in const generics. #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)] diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs index 018fa22715403..295cb14646109 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs @@ -170,7 +170,7 @@ impl<'tcx> InhabitedPredicate<'tcx> { match self { Self::ConstIsZero(c) => { let c = ty::EarlyBinder::bind(c).subst(tcx, substs); - let pred = match c.kind().try_to_target_usize(tcx) { + let pred = match c.try_to_target_usize(tcx) { Some(0) => Self::True, Some(1..) => Self::False, None => Self::ConstIsZero(c), diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index 4223502848ef8..b92d84152b47d 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -197,7 +197,7 @@ fn inhabited_predicate_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> InhabitedP // If we can evaluate the array length before having a `ParamEnv`, then // we can simplify the predicate. This is an optimization. - Array(ty, len) => match len.kind().try_to_target_usize(tcx) { + Array(ty, len) => match len.try_to_target_usize(tcx) { Some(0) => InhabitedPredicate::True, Some(1..) => ty.inhabited_predicate(tcx), None => ty.inhabited_predicate(tcx).or(tcx, InhabitedPredicate::ConstIsZero(len)), diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index b443708b22c71..c100c45b61a72 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -66,6 +66,10 @@ use std::{fmt, str}; pub use crate::ty::diagnostics::*; pub use rustc_type_ir::AliasKind::*; +pub use rustc_type_ir::ConstKind::{ + Bound as BoundCt, Error as ErrorCt, Expr as ExprCt, Infer as InferCt, Param as ParamCt, + Placeholder as PlaceholderCt, Unevaluated, Value, +}; pub use rustc_type_ir::DynKind::*; pub use rustc_type_ir::InferTy::*; pub use rustc_type_ir::RegionKind::*; diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index fa72483271820..4a639a2a0fe6e 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -11,6 +11,7 @@ use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt}; use rustc_hir::def::Namespace; use rustc_index::{Idx, IndexVec}; use rustc_target::abi::TyAndLayout; +use rustc_type_ir::ConstKind; use std::fmt; use std::ops::ControlFlow; @@ -710,7 +711,18 @@ impl<'tcx> TypeSuperFoldable> for ty::Const<'tcx> { folder: &mut F, ) -> Result { let ty = self.ty().try_fold_with(folder)?; - let kind = self.kind().try_fold_with(folder)?; + let kind = match self.kind() { + ConstKind::Param(p) => ConstKind::Param(p.try_fold_with(folder)?), + ConstKind::Infer(i) => ConstKind::Infer(i.try_fold_with(folder)?), + ConstKind::Bound(d, b) => { + ConstKind::Bound(d.try_fold_with(folder)?, b.try_fold_with(folder)?) + } + ConstKind::Placeholder(p) => ConstKind::Placeholder(p.try_fold_with(folder)?), + ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.try_fold_with(folder)?), + ConstKind::Value(v) => ConstKind::Value(v.try_fold_with(folder)?), + ConstKind::Error(e) => ConstKind::Error(e.try_fold_with(folder)?), + ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?), + }; if ty != self.ty() || kind != self.kind() { Ok(folder.interner().mk_ct_from_kind(kind, ty)) } else { @@ -725,7 +737,19 @@ impl<'tcx> TypeSuperVisitable> for ty::Const<'tcx> { visitor: &mut V, ) -> ControlFlow { self.ty().visit_with(visitor)?; - self.kind().visit_with(visitor) + match self.kind() { + ConstKind::Param(p) => p.visit_with(visitor), + ConstKind::Infer(i) => i.visit_with(visitor), + ConstKind::Bound(d, b) => { + d.visit_with(visitor)?; + b.visit_with(visitor) + } + ConstKind::Placeholder(p) => p.visit_with(visitor), + ConstKind::Unevaluated(uv) => uv.visit_with(visitor), + ConstKind::Value(v) => v.visit_with(visitor), + ConstKind::Error(e) => e.visit_with(visitor), + ConstKind::Expr(e) => e.visit_with(visitor), + } } } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index bb08deff294cf..464301251065b 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1306,7 +1306,7 @@ pub fn needs_drop_components<'tcx>( ty::Array(elem_ty, size) => { match needs_drop_components(*elem_ty, target_layout) { Ok(v) if v.is_empty() => Ok(v), - res => match size.kind().try_to_bits(target_layout.pointer_size) { + res => match size.try_to_bits(target_layout.pointer_size) { // Arrays of size zero don't need drop, even if their element // type does. Some(0) => Ok(SmallVec::new()), diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 254ede4e6a00a..ec7032cd3bf54 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -230,7 +230,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { self.write_str("[")?; self = self.print_type(ty)?; self.write_str("; ")?; - if let Some(size) = size.kind().try_to_bits(self.tcx().data_layout.pointer_size) { + if let Some(size) = size.try_to_bits(self.tcx().data_layout.pointer_size) { write!(self, "{size}")? } else if let ty::ConstKind::Param(param) = size.kind() { self = param.print(self)? diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 85825513ce96b..2f978102ff2df 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -112,7 +112,7 @@ fn encode_const<'tcx>( let _ = write!(s, "{value}"); } - if let Some(scalar_int) = c.kind().try_to_scalar_int() { + if let Some(scalar_int) = c.try_to_scalar_int() { let signed = c.ty().is_signed(); match scalar_int.size().bits() { 8 if signed => push_signed_value(&mut s, scalar_int.try_to_i8().unwrap(), 0), @@ -504,8 +504,7 @@ fn encode_ty<'tcx>( let _ = write!( s, "{}", - &len.kind() - .try_to_scalar() + &len.try_to_scalar() .unwrap() .to_u64() .unwrap_or_else(|_| panic!("failed to convert length to u64")) @@ -815,7 +814,6 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio ty::Array(ty0, len) => { let len = len - .kind() .try_to_scalar() .unwrap() .to_u64() diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index c52ae4dc8e93d..d1d5af4895758 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -651,7 +651,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { .builtin_deref(true) .expect("tried to dereference on non-ptr type") .ty; - // FIXME: add an assert that we only do this for valtrees. + // FIXME(const_generics): add an assert that we only do this for valtrees. let dereferenced_const = self.tcx.mk_ct_from_kind(ct.kind(), pointee_ty); self = dereferenced_const.print(self)?; } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 10bd027b6848a..1e4d30f48b2dc 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -278,7 +278,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // Arrays give us `[]`, `[{ty}; _]` and `[{ty}; N]` if let ty::Array(aty, len) = self_ty.kind() { flags.push((sym::_Self, Some("[]".to_string()))); - let len = len.kind().try_to_value().and_then(|v| v.try_to_target_usize(self.tcx)); + let len = len.try_to_value().and_then(|v| v.try_to_target_usize(self.tcx)); flags.push((sym::_Self, Some(format!("[{}; _]", aty)))); if let Some(n) = len { flags.push((sym::_Self, Some(format!("[{}; {}]", aty, n)))); diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 3d96c422256fe..2d8c260126dfd 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -528,7 +528,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { debug!("equating consts:\nc1= {:?}\nc2= {:?}", c1, c2); use rustc_hir::def::DefKind; - use ty::ConstKind::Unevaluated; + use ty::Unevaluated; match (c1.kind(), c2.kind()) { (Unevaluated(a), Unevaluated(b)) if a.def == b.def && tcx.def_kind(a.def) == DefKind::AssocConst => diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index eb11163de4212..7d511a30d746b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -897,7 +897,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); use rustc_hir::def::DefKind; - use ty::ConstKind::Unevaluated; + use ty::Unevaluated; match (c1.kind(), c2.kind()) { (Unevaluated(a), Unevaluated(b)) if a.def == b.def && tcx.def_kind(a.def) == DefKind::AssocConst => diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index dd3cda8ec5277..1e1bb2a1d962f 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -689,7 +689,7 @@ pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'t mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() { ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)), ty::Array(sub_type, len) => match sub_type.kind() { - ty::Float(FloatTy::F32) => match len.kind().try_to_target_usize(lcx.tcx) { + ty::Float(FloatTy::F32) => match len.try_to_target_usize(lcx.tcx) { Some(len) => alloc .inner() .inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap())) @@ -700,7 +700,7 @@ pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'t .map(Constant::Vec), _ => None, }, - ty::Float(FloatTy::F64) => match len.kind().try_to_target_usize(lcx.tcx) { + ty::Float(FloatTy::F64) => match len.try_to_target_usize(lcx.tcx) { Some(len) => alloc .inner() .inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * usize::try_from(len).unwrap())) diff --git a/tests/mir-opt/issue_99325.main.built.after.mir b/tests/mir-opt/issue_99325.main.built.after.mir index d8a88a0635c5e..0fe66d3fb7021 100644 --- a/tests/mir-opt/issue_99325.main.built.after.mir +++ b/tests/mir-opt/issue_99325.main.built.after.mir @@ -2,7 +2,7 @@ | User Type Annotations | 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Branch([Leaf(0x41), Leaf(0x41), Leaf(0x41), Leaf(0x41)]) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:10:16: 10:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated([], DefId(0:8 ~ issue_99325[22bb]::main::{constant#1})) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: UnevaluatedConst { def: DefId(0:8 ~ issue_99325[22bb]::main::{constant#1}), substs: [] } }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); From 4169d0f756dde8b3e692610bddb3c948c5cd53ea Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 5 Jul 2023 17:39:40 +1000 Subject: [PATCH 19/22] Narrow trait `CoverageInfoBuilderMethods` down to just one method This effectively inlines most of `FunctionCx::codegen_coverage` into the LLVM implementation of `CoverageInfoBuilderMethods`. --- .../rustc_codegen_gcc/src/coverageinfo.rs | 29 +-------- .../src/coverageinfo/mod.rs | 59 ++++++++++++++++++- .../rustc_codegen_ssa/src/mir/coverageinfo.rs | 41 +------------ .../rustc_codegen_ssa/src/mir/statement.rs | 2 +- .../src/traits/coverageinfo.rs | 40 ++----------- 5 files changed, 69 insertions(+), 102 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/coverageinfo.rs b/compiler/rustc_codegen_gcc/src/coverageinfo.rs index 872fc2472e223..41fc096131b98 100644 --- a/compiler/rustc_codegen_gcc/src/coverageinfo.rs +++ b/compiler/rustc_codegen_gcc/src/coverageinfo.rs @@ -1,40 +1,15 @@ use gccjit::RValue; use rustc_codegen_ssa::traits::{CoverageInfoBuilderMethods, CoverageInfoMethods}; use rustc_hir::def_id::DefId; -use rustc_middle::mir::coverage::{ - CodeRegion, - CounterValueReference, - ExpressionOperandId, - InjectedExpressionId, - Op, -}; +use rustc_middle::mir::Coverage; use rustc_middle::ty::Instance; use crate::builder::Builder; use crate::context::CodegenCx; impl<'a, 'gcc, 'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { - fn set_function_source_hash( - &mut self, - _instance: Instance<'tcx>, - _function_source_hash: u64, - ) -> bool { - unimplemented!(); - } - - fn add_coverage_counter(&mut self, _instance: Instance<'tcx>, _id: CounterValueReference, _region: CodeRegion) -> bool { - // TODO(antoyo) - false - } - - fn add_coverage_counter_expression(&mut self, _instance: Instance<'tcx>, _id: InjectedExpressionId, _lhs: ExpressionOperandId, _op: Op, _rhs: ExpressionOperandId, _region: Option) -> bool { - // TODO(antoyo) - false - } - - fn add_coverage_unreachable(&mut self, _instance: Instance<'tcx>, _region: CodeRegion) -> bool { + fn add_coverage(&mut self, _instance: Instance<'tcx>, _coverage: &Coverage) { // TODO(antoyo) - false } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index cd261293e9b2d..899e9221ed736 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -17,10 +17,11 @@ use rustc_hir::def_id::DefId; use rustc_llvm::RustString; use rustc_middle::bug; use rustc_middle::mir::coverage::{ - CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, Op, + CodeRegion, CounterValueReference, CoverageKind, ExpressionOperandId, InjectedExpressionId, Op, }; +use rustc_middle::mir::Coverage; use rustc_middle::ty; -use rustc_middle::ty::layout::FnAbiOf; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::Instance; @@ -94,6 +95,54 @@ impl<'ll, 'tcx> CoverageInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { } impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { + fn add_coverage(&mut self, instance: Instance<'tcx>, coverage: &Coverage) { + let bx = self; + + let Coverage { kind, code_region } = coverage.clone(); + match kind { + CoverageKind::Counter { function_source_hash, id } => { + if bx.set_function_source_hash(instance, function_source_hash) { + // If `set_function_source_hash()` returned true, the coverage map is enabled, + // so continue adding the counter. + if let Some(code_region) = code_region { + // Note: Some counters do not have code regions, but may still be referenced + // from expressions. In that case, don't add the counter to the coverage map, + // but do inject the counter intrinsic. + bx.add_coverage_counter(instance, id, code_region); + } + + let coverageinfo = bx.tcx().coverageinfo(instance.def); + + let fn_name = bx.get_pgo_func_name_var(instance); + let hash = bx.const_u64(function_source_hash); + let num_counters = bx.const_u32(coverageinfo.num_counters); + let index = bx.const_u32(id.zero_based_index()); + debug!( + "codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})", + fn_name, hash, num_counters, index, + ); + bx.instrprof_increment(fn_name, hash, num_counters, index); + } + } + CoverageKind::Expression { id, lhs, op, rhs } => { + bx.add_coverage_counter_expression(instance, id, lhs, op, rhs, code_region); + } + CoverageKind::Unreachable => { + bx.add_coverage_unreachable( + instance, + code_region.expect("unreachable regions always have code regions"), + ); + } + } + } +} + +// These methods used to be part of trait `CoverageInfoBuilderMethods`, but +// after moving most coverage code out of SSA they are now just ordinary methods. +impl<'tcx> Builder<'_, '_, 'tcx> { + /// Returns true if the function source hash was added to the coverage map (even if it had + /// already been added, for this instance). Returns false *only* if `-C instrument-coverage` is + /// not enabled (a coverage map is not being generated). fn set_function_source_hash( &mut self, instance: Instance<'tcx>, @@ -115,6 +164,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { } } + /// Returns true if the counter was added to the coverage map; false if `-C instrument-coverage` + /// is not enabled (a coverage map is not being generated). fn add_coverage_counter( &mut self, instance: Instance<'tcx>, @@ -137,6 +188,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { } } + /// Returns true if the expression was added to the coverage map; false if + /// `-C instrument-coverage` is not enabled (a coverage map is not being generated). fn add_coverage_counter_expression( &mut self, instance: Instance<'tcx>, @@ -163,6 +216,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { } } + /// Returns true if the region was added to the coverage map; false if `-C instrument-coverage` + /// is not enabled (a coverage map is not being generated). fn add_coverage_unreachable(&mut self, instance: Instance<'tcx>, region: CodeRegion) -> bool { if let Some(coverage_context) = self.coverage_context() { debug!( diff --git a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs index f1fe495282abc..ee70465966d0c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs @@ -1,13 +1,12 @@ use crate::traits::*; -use rustc_middle::mir::coverage::*; use rustc_middle::mir::Coverage; use rustc_middle::mir::SourceScope; use super::FunctionCx; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { - pub fn codegen_coverage(&self, bx: &mut Bx, coverage: Coverage, scope: SourceScope) { + pub fn codegen_coverage(&self, bx: &mut Bx, coverage: &Coverage, scope: SourceScope) { // Determine the instance that coverage data was originally generated for. let instance = if let Some(inlined) = scope.inlined_instance(&self.mir.source_scopes) { self.monomorphize(inlined) @@ -15,41 +14,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.instance }; - let Coverage { kind, code_region } = coverage; - match kind { - CoverageKind::Counter { function_source_hash, id } => { - if bx.set_function_source_hash(instance, function_source_hash) { - // If `set_function_source_hash()` returned true, the coverage map is enabled, - // so continue adding the counter. - if let Some(code_region) = code_region { - // Note: Some counters do not have code regions, but may still be referenced - // from expressions. In that case, don't add the counter to the coverage map, - // but do inject the counter intrinsic. - bx.add_coverage_counter(instance, id, code_region); - } - - let coverageinfo = bx.tcx().coverageinfo(instance.def); - - let fn_name = bx.get_pgo_func_name_var(instance); - let hash = bx.const_u64(function_source_hash); - let num_counters = bx.const_u32(coverageinfo.num_counters); - let index = bx.const_u32(id.zero_based_index()); - debug!( - "codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})", - fn_name, hash, num_counters, index, - ); - bx.instrprof_increment(fn_name, hash, num_counters, index); - } - } - CoverageKind::Expression { id, lhs, op, rhs } => { - bx.add_coverage_counter_expression(instance, id, lhs, op, rhs, code_region); - } - CoverageKind::Unreachable => { - bx.add_coverage_unreachable( - instance, - code_region.expect("unreachable regions always have code regions"), - ); - } - } + // Handle the coverage info in a backend-specific way. + bx.add_coverage(instance, coverage); } } diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index 314d364c0c2a3..899e41265bba5 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -65,7 +65,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } mir::StatementKind::Coverage(box ref coverage) => { - self.codegen_coverage(bx, coverage.clone(), statement.source_info.scope); + self.codegen_coverage(bx, coverage, statement.source_info.scope); } mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => { let op_val = self.codegen_operand(bx, op); diff --git a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs index e77201cf0c800..75b125b3016a3 100644 --- a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs @@ -1,6 +1,6 @@ use super::BackendTypes; use rustc_hir::def_id::DefId; -use rustc_middle::mir::coverage::*; +use rustc_middle::mir::Coverage; use rustc_middle::ty::Instance; pub trait CoverageInfoMethods<'tcx>: BackendTypes { @@ -21,37 +21,9 @@ pub trait CoverageInfoMethods<'tcx>: BackendTypes { } pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes { - /// Returns true if the function source hash was added to the coverage map (even if it had - /// already been added, for this instance). Returns false *only* if `-C instrument-coverage` is - /// not enabled (a coverage map is not being generated). - fn set_function_source_hash( - &mut self, - instance: Instance<'tcx>, - function_source_hash: u64, - ) -> bool; - - /// Returns true if the counter was added to the coverage map; false if `-C instrument-coverage` - /// is not enabled (a coverage map is not being generated). - fn add_coverage_counter( - &mut self, - instance: Instance<'tcx>, - index: CounterValueReference, - region: CodeRegion, - ) -> bool; - - /// Returns true if the expression was added to the coverage map; false if - /// `-C instrument-coverage` is not enabled (a coverage map is not being generated). - fn add_coverage_counter_expression( - &mut self, - instance: Instance<'tcx>, - id: InjectedExpressionId, - lhs: ExpressionOperandId, - op: Op, - rhs: ExpressionOperandId, - region: Option, - ) -> bool; - - /// Returns true if the region was added to the coverage map; false if `-C instrument-coverage` - /// is not enabled (a coverage map is not being generated). - fn add_coverage_unreachable(&mut self, instance: Instance<'tcx>, region: CodeRegion) -> bool; + /// Handle the MIR coverage info in a backend-specific way. + /// + /// This can potentially be a no-op in backends that don't support + /// coverage instrumentation. + fn add_coverage(&mut self, instance: Instance<'tcx>, coverage: &Coverage); } From 9c430d38cf10ec3fab459be00e87057e5cce55b0 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 5 Jul 2023 17:56:10 +1000 Subject: [PATCH 20/22] Remove trait `CoverageInfoMethods`, since non-LLVM backends don't need it These methods are only ever called from within `rustc_codegen_llvm`, so they can just be declared there as well. --- .../rustc_codegen_gcc/src/coverageinfo.rs | 35 +------------------ .../src/coverageinfo/mapgen.rs | 2 +- .../src/coverageinfo/mod.rs | 14 +++++--- .../src/traits/coverageinfo.rs | 18 ---------- compiler/rustc_codegen_ssa/src/traits/mod.rs | 4 +-- 5 files changed, 13 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/coverageinfo.rs b/compiler/rustc_codegen_gcc/src/coverageinfo.rs index 41fc096131b98..849e9886ef39d 100644 --- a/compiler/rustc_codegen_gcc/src/coverageinfo.rs +++ b/compiler/rustc_codegen_gcc/src/coverageinfo.rs @@ -1,44 +1,11 @@ -use gccjit::RValue; -use rustc_codegen_ssa::traits::{CoverageInfoBuilderMethods, CoverageInfoMethods}; -use rustc_hir::def_id::DefId; +use rustc_codegen_ssa::traits::CoverageInfoBuilderMethods; use rustc_middle::mir::Coverage; use rustc_middle::ty::Instance; use crate::builder::Builder; -use crate::context::CodegenCx; impl<'a, 'gcc, 'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { fn add_coverage(&mut self, _instance: Instance<'tcx>, _coverage: &Coverage) { // TODO(antoyo) } } - -impl<'gcc, 'tcx> CoverageInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> { - fn coverageinfo_finalize(&self) { - // TODO(antoyo) - } - - fn get_pgo_func_name_var(&self, _instance: Instance<'tcx>) -> RValue<'gcc> { - unimplemented!(); - } - - /// Functions with MIR-based coverage are normally codegenned _only_ if - /// called. LLVM coverage tools typically expect every function to be - /// defined (even if unused), with at least one call to LLVM intrinsic - /// `instrprof.increment`. - /// - /// Codegen a small function that will never be called, with one counter - /// that will never be incremented. - /// - /// For used/called functions, the coverageinfo was already added to the - /// `function_coverage_map` (keyed by function `Instance`) during codegen. - /// But in this case, since the unused function was _not_ previously - /// codegenned, collect the coverage `CodeRegion`s from the MIR and add - /// them. The first `CodeRegion` is used to add a single counter, with the - /// same counter ID used in the injected `instrprof.increment` intrinsic - /// call. Since the function is never called, all other `CodeRegion`s can be - /// added as `unreachable_region`s. - fn define_unused_fn(&self, _def_id: DefId) { - unimplemented!(); - } -} diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 21a1ac348443e..57c5d39395770 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -4,7 +4,7 @@ use crate::llvm; use llvm::coverageinfo::CounterMappingRegion; use rustc_codegen_ssa::coverageinfo::map::{Counter, CounterExpression}; -use rustc_codegen_ssa::traits::{ConstMethods, CoverageInfoMethods}; +use rustc_codegen_ssa::traits::ConstMethods; use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 899e9221ed736..246f0c4fe1581 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -8,8 +8,8 @@ use libc::c_uint; use llvm::coverageinfo::CounterMappingRegion; use rustc_codegen_ssa::coverageinfo::map::{CounterExpression, FunctionCoverage}; use rustc_codegen_ssa::traits::{ - BaseTypeMethods, BuilderMethods, ConstMethods, CoverageInfoBuilderMethods, CoverageInfoMethods, - MiscMethods, StaticMethods, + BaseTypeMethods, BuilderMethods, ConstMethods, CoverageInfoBuilderMethods, MiscMethods, + StaticMethods, }; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; @@ -54,11 +54,17 @@ impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> { } } -impl<'ll, 'tcx> CoverageInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { - fn coverageinfo_finalize(&self) { +// These methods used to be part of trait `CoverageInfoMethods`, which no longer +// exists after most coverage code was moved out of SSA. +impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { + pub(crate) fn coverageinfo_finalize(&self) { mapgen::finalize(self) } + /// For LLVM codegen, returns a function-specific `Value` for a global + /// string, to hold the function name passed to LLVM intrinsic + /// `instrprof.increment()`. The `Value` is only created once per instance. + /// Multiple invocations with the same instance return the same `Value`. fn get_pgo_func_name_var(&self, instance: Instance<'tcx>) -> &'ll llvm::Value { if let Some(coverage_context) = self.coverage_context() { debug!("getting pgo_func_name_var for instance={:?}", instance); diff --git a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs index 75b125b3016a3..7e8de0ddc5bf4 100644 --- a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs @@ -1,25 +1,7 @@ use super::BackendTypes; -use rustc_hir::def_id::DefId; use rustc_middle::mir::Coverage; use rustc_middle::ty::Instance; -pub trait CoverageInfoMethods<'tcx>: BackendTypes { - fn coverageinfo_finalize(&self); - - /// Codegen a small function that will never be called, with one counter - /// that will never be incremented, that gives LLVM coverage tools a - /// function definition it needs in order to resolve coverage map references - /// to unused functions. This is necessary so unused functions will appear - /// as uncovered (coverage execution count `0`) in LLVM coverage reports. - fn define_unused_fn(&self, def_id: DefId); - - /// For LLVM codegen, returns a function-specific `Value` for a global - /// string, to hold the function name passed to LLVM intrinsic - /// `instrprof.increment()`. The `Value` is only created once per instance. - /// Multiple invocations with the same instance return the same `Value`. - fn get_pgo_func_name_var(&self, instance: Instance<'tcx>) -> Self::Value; -} - pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes { /// Handle the MIR coverage info in a backend-specific way. /// diff --git a/compiler/rustc_codegen_ssa/src/traits/mod.rs b/compiler/rustc_codegen_ssa/src/traits/mod.rs index 782fdadbfb87c..8cb58bd4c704d 100644 --- a/compiler/rustc_codegen_ssa/src/traits/mod.rs +++ b/compiler/rustc_codegen_ssa/src/traits/mod.rs @@ -33,7 +33,7 @@ pub use self::asm::{AsmBuilderMethods, AsmMethods, GlobalAsmOperandRef, InlineAs pub use self::backend::{Backend, BackendTypes, CodegenBackend, ExtraBackendMethods}; pub use self::builder::{BuilderMethods, OverflowOp}; pub use self::consts::ConstMethods; -pub use self::coverageinfo::{CoverageInfoBuilderMethods, CoverageInfoMethods}; +pub use self::coverageinfo::CoverageInfoBuilderMethods; pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods}; pub use self::declare::PreDefineMethods; pub use self::intrinsic::IntrinsicCallMethods; @@ -59,7 +59,6 @@ pub trait CodegenMethods<'tcx>: + MiscMethods<'tcx> + ConstMethods<'tcx> + StaticMethods - + CoverageInfoMethods<'tcx> + DebugInfoMethods<'tcx> + AsmMethods<'tcx> + PreDefineMethods<'tcx> @@ -75,7 +74,6 @@ impl<'tcx, T> CodegenMethods<'tcx> for T where + MiscMethods<'tcx> + ConstMethods<'tcx> + StaticMethods - + CoverageInfoMethods<'tcx> + DebugInfoMethods<'tcx> + AsmMethods<'tcx> + PreDefineMethods<'tcx> From cb570d6bc1251f32a07d8ce173dc735be78a325f Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 5 Jul 2023 18:04:58 +1000 Subject: [PATCH 21/22] Move `coverageinfo::ffi` and `coverageinfo::map` out of SSA --- .../src/coverageinfo/ffi.rs | 0 .../src/coverageinfo/map_data.rs} | 1 + compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs | 2 +- compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs | 4 +++- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 2 +- compiler/rustc_codegen_ssa/src/coverageinfo/mod.rs | 2 -- compiler/rustc_codegen_ssa/src/lib.rs | 1 - 7 files changed, 6 insertions(+), 6 deletions(-) rename compiler/{rustc_codegen_ssa => rustc_codegen_llvm}/src/coverageinfo/ffi.rs (100%) rename compiler/{rustc_codegen_ssa/src/coverageinfo/map.rs => rustc_codegen_llvm/src/coverageinfo/map_data.rs} (99%) delete mode 100644 compiler/rustc_codegen_ssa/src/coverageinfo/mod.rs diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs similarity index 100% rename from compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs rename to compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs similarity index 99% rename from compiler/rustc_codegen_ssa/src/coverageinfo/map.rs rename to compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index e4da3b8de0512..06844afd6b870 100644 --- a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -1,6 +1,7 @@ pub use super::ffi::*; use rustc_index::{IndexSlice, IndexVec}; +use rustc_middle::bug; use rustc_middle::mir::coverage::{ CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, InjectedExpressionIndex, MappedExpressionIndex, Op, diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 57c5d39395770..a1ff2aa662500 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -1,9 +1,9 @@ use crate::common::CodegenCx; use crate::coverageinfo; +use crate::coverageinfo::map_data::{Counter, CounterExpression}; use crate::llvm; use llvm::coverageinfo::CounterMappingRegion; -use rustc_codegen_ssa::coverageinfo::map::{Counter, CounterExpression}; use rustc_codegen_ssa::traits::ConstMethods; use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def::DefKind; diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 246f0c4fe1581..839a7f333ba4f 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -3,10 +3,10 @@ use crate::llvm; use crate::abi::Abi; use crate::builder::Builder; use crate::common::CodegenCx; +use crate::coverageinfo::map_data::{CounterExpression, FunctionCoverage}; use libc::c_uint; use llvm::coverageinfo::CounterMappingRegion; -use rustc_codegen_ssa::coverageinfo::map::{CounterExpression, FunctionCoverage}; use rustc_codegen_ssa::traits::{ BaseTypeMethods, BuilderMethods, ConstMethods, CoverageInfoBuilderMethods, MiscMethods, StaticMethods, @@ -28,6 +28,8 @@ use rustc_middle::ty::Instance; use std::cell::RefCell; use std::ffi::CString; +mod ffi; +pub(crate) mod map_data; pub mod mapgen; const UNUSED_FUNCTION_COUNTER_ID: CounterValueReference = CounterValueReference::START; diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index b667bc4f6d443..8ee40b98e2ddd 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1,7 +1,7 @@ #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] -use rustc_codegen_ssa::coverageinfo::map as coverage_map; +use crate::coverageinfo::map_data as coverage_map; use super::debuginfo::{ DIArray, DIBasicType, DIBuilder, DICompositeType, DIDerivedType, DIDescriptor, DIEnumerator, diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/mod.rs b/compiler/rustc_codegen_ssa/src/coverageinfo/mod.rs deleted file mode 100644 index 569fd3f1a516d..0000000000000 --- a/compiler/rustc_codegen_ssa/src/coverageinfo/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod ffi; -pub mod map; diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index c26a7422fdd24..be4c81638d63f 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -48,7 +48,6 @@ pub mod back; pub mod base; pub mod codegen_attrs; pub mod common; -pub mod coverageinfo; pub mod debuginfo; pub mod errors; pub mod glue; From 6cc37bbee074bb2746d8cfe4456c1d88f7db5c2f Mon Sep 17 00:00:00 2001 From: Havard Eidnes Date: Wed, 5 Jul 2023 10:34:26 +0000 Subject: [PATCH 22/22] Add support for NetBSD/riscv64 aka. riscv64gc-unknown-netbsd. --- compiler/rustc_target/src/spec/mod.rs | 1 + .../src/spec/riscv64gc_unknown_netbsd.rs | 19 +++++++++++++++++++ library/core/src/ffi/mod.rs | 7 ++++++- src/bootstrap/llvm.rs | 5 ++++- src/doc/rustc/src/platform-support.md | 1 + src/doc/rustc/src/platform-support/netbsd.md | 1 + 6 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 compiler/rustc_target/src/spec/riscv64gc_unknown_netbsd.rs diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 2e5bb3db8867d..2365dfaf1af80 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1325,6 +1325,7 @@ supported_targets! { ("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf), ("i686-unknown-netbsd", i686_unknown_netbsd), ("powerpc-unknown-netbsd", powerpc_unknown_netbsd), + ("riscv64gc-unknown-netbsd", riscv64gc_unknown_netbsd), ("sparc64-unknown-netbsd", sparc64_unknown_netbsd), ("x86_64-unknown-netbsd", x86_64_unknown_netbsd), diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_netbsd.rs new file mode 100644 index 0000000000000..a89bd363a47eb --- /dev/null +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_netbsd.rs @@ -0,0 +1,19 @@ +use crate::spec::{CodeModel, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + llvm_target: "riscv64-unknown-netbsd".into(), + pointer_width: 64, + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), + arch: "riscv64".into(), + options: TargetOptions { + code_model: Some(CodeModel::Medium), + cpu: "generic-rv64".into(), + features: "+m,+a,+f,+d,+c".into(), + llvm_abiname: "lp64d".into(), + max_atomic_width: Some(64), + mcount: "__mcount".into(), + ..super::netbsd_base::opts() + }, + } +} diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 7437722fd0625..0488c807604d3 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -132,7 +132,12 @@ mod c_char_definition { ), all( target_os = "netbsd", - any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc") + any( + target_arch = "aarch64", + target_arch = "arm", + target_arch = "powerpc", + target_arch = "riscv64" + ) ), all( target_os = "vxworks", diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/llvm.rs index 4752b1f7ea1e4..c4916a21c0fbf 100644 --- a/src/bootstrap/llvm.rs +++ b/src/bootstrap/llvm.rs @@ -380,7 +380,10 @@ impl Step for Llvm { cfg.define("LLVM_LINK_LLVM_DYLIB", "ON"); } - if target.starts_with("riscv") && !target.contains("freebsd") && !target.contains("openbsd") + if target.starts_with("riscv") + && !target.contains("freebsd") + && !target.contains("openbsd") + && !target.contains("netbsd") { // RISC-V GCC erroneously requires linking against // `libatomic` when using 1-byte and 2-byte C++ diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index e9487ef81e795..d2a25e612ec7b 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -305,6 +305,7 @@ target | std | host | notes `riscv64gc-unknown-freebsd` | | | RISC-V FreeBSD `riscv64gc-unknown-fuchsia` | | | RISC-V Fuchsia `riscv64gc-unknown-linux-musl` | | | RISC-V Linux (kernel 4.20, musl 1.2.0) +[`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ? | RISC-V NetBSD [`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64 `s390x-unknown-linux-musl` | | | S390x Linux (kernel 3.2, MUSL) `sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux diff --git a/src/doc/rustc/src/platform-support/netbsd.md b/src/doc/rustc/src/platform-support/netbsd.md index a1969524a20e4..23f4488de6e7f 100644 --- a/src/doc/rustc/src/platform-support/netbsd.md +++ b/src/doc/rustc/src/platform-support/netbsd.md @@ -22,6 +22,7 @@ are currently defined running NetBSD: | `i686-unknown-netbsd` | [32-bit i386 with SSE](https://wiki.netbsd.org/ports/i386/) | | `mipsel-unknown-netbsd` | [32-bit mips, requires mips32 cpu support](https://wiki.netbsd.org/ports/evbmips/) | | `powerpc-unknown-netbsd` | [Various 32-bit PowerPC systems, e.g. MacPPC](https://wiki.netbsd.org/ports/macppc/) | +| `riscv64gc-unknown-netbsd` | [64-bit RISC-V](https://wiki.netbsd.org/ports/riscv/) | `sparc64-unknown-netbsd` | [Sun UltraSPARC systems](https://wiki.netbsd.org/ports/sparc64/) | All use the "native" `stdc++` library which goes along with the natively