diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs index f2ceb4702643a..f101c595bdf35 100644 --- a/compiler/rustc_hir_analysis/src/autoderef.rs +++ b/compiler/rustc_hir_analysis/src/autoderef.rs @@ -1,6 +1,6 @@ use crate::errors::AutoDerefReachedRecursionLimit; +use crate::traits; use crate::traits::query::evaluate_obligation::InferCtxtExt; -use crate::traits::{self, TraitEngine, TraitEngineExt}; use rustc_infer::infer::InferCtxt; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -8,7 +8,7 @@ use rustc_session::Limit; use rustc_span::def_id::LocalDefId; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::Span; -use rustc_trait_selection::traits::StructurallyNormalizeExt; +use rustc_trait_selection::traits::ObligationCtxt; #[derive(Copy, Clone, Debug)] pub enum AutoderefKind { @@ -167,25 +167,19 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { &self, ty: Ty<'tcx>, ) -> Option<(Ty<'tcx>, Vec>)> { - let mut fulfill_cx = >::new(self.infcx); - - let cause = traits::ObligationCause::misc(self.span, self.body_id); - let normalized_ty = match self - .infcx - .at(&cause, self.param_env) - .structurally_normalize(ty, &mut *fulfill_cx) - { - Ok(normalized_ty) => normalized_ty, - Err(errors) => { - // This shouldn't happen, except for evaluate/fulfill mismatches, - // but that's not a reason for an ICE (`predicate_may_hold` is conservative - // by design). - debug!(?errors, "encountered errors while fulfilling"); - return None; - } + let ocx = ObligationCtxt::new(self.infcx); + let Ok(normalized_ty) = ocx.structurally_normalize( + &traits::ObligationCause::misc(self.span, self.body_id), + self.param_env, + ty, + ) else { + // We shouldn't have errors here, except for evaluate/fulfill mismatches, + // but that's not a reason for an ICE (`predicate_may_hold` is conservative + // by design). + // FIXME(-Znext-solver): This *actually* shouldn't happen then. + return None; }; - - let errors = fulfill_cx.select_where_possible(self.infcx); + let errors = ocx.select_where_possible(); if !errors.is_empty() { // This shouldn't happen, except for evaluate/fulfill mismatches, // but that's not a reason for an ICE (`predicate_may_hold` is conservative @@ -194,7 +188,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { return None; } - Some((normalized_ty, fulfill_cx.pending_obligations())) + Some((normalized_ty, ocx.into_pending_obligations())) } /// Returns the final type we ended up with, which may be an inference diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 825276aef421c..076c1936ded8d 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -45,8 +45,7 @@ use rustc_hir::Expr; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_infer::infer::type_variable::TypeVariableOrigin; use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult}; -use rustc_infer::traits::TraitEngineExt as _; -use rustc_infer::traits::{IfExpressionCause, MatchExpressionArmCause, TraitEngine}; +use rustc_infer::traits::{IfExpressionCause, MatchExpressionArmCause}; use rustc_infer::traits::{Obligation, PredicateObligation}; use rustc_middle::lint::in_external_macro; use rustc_middle::traits::BuiltinImplSource; @@ -65,7 +64,6 @@ use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; -use rustc_trait_selection::traits::TraitEngineExt as _; use rustc_trait_selection::traits::{ self, NormalizeExt, ObligationCause, ObligationCauseCode, ObligationCtxt, }; @@ -164,11 +162,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Filter these cases out to make sure our coercion is more accurate. match res { Ok(InferOk { value, obligations }) if self.next_trait_solver() => { - let mut fulfill_cx = >::new(self); - fulfill_cx.register_predicate_obligations(self, obligations); - let errs = fulfill_cx.select_where_possible(self); - if errs.is_empty() { - Ok(InferOk { value, obligations: fulfill_cx.pending_obligations() }) + let ocx = ObligationCtxt::new(self); + ocx.register_obligations(obligations); + if ocx.select_where_possible().is_empty() { + Ok(InferOk { value, obligations: ocx.into_pending_obligations() }) } else { Err(TypeError::Mismatch) } @@ -631,13 +628,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // but we need to constrain vars before processing goals mentioning // them. Some(ty::PredicateKind::AliasRelate(..)) => { - let mut fulfill_cx = >::new(self); - fulfill_cx.register_predicate_obligation(self, obligation); - let errs = fulfill_cx.select_where_possible(self); - if !errs.is_empty() { + let ocx = ObligationCtxt::new(self); + ocx.register_obligation(obligation); + if !ocx.select_where_possible().is_empty() { return Err(TypeError::Mismatch); } - coercion.obligations.extend(fulfill_cx.pending_obligations()); + coercion.obligations.extend(ocx.into_pending_obligations()); continue; } _ => { diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index e3611ab28e532..f77a611586180 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -206,6 +206,18 @@ impl<'tcx> FulfillmentError<'tcx> { ) -> FulfillmentError<'tcx> { FulfillmentError { obligation, code, root_obligation } } + + pub fn is_true_error(&self) -> bool { + match self.code { + FulfillmentErrorCode::SelectionError(_) + | FulfillmentErrorCode::ProjectionError(_) + | FulfillmentErrorCode::SubtypeError(_, _) + | FulfillmentErrorCode::ConstEquateError(_, _) => true, + FulfillmentErrorCode::Cycle(_) | FulfillmentErrorCode::Ambiguity { overflow: _ } => { + false + } + } + } } impl<'tcx> PolyTraitObligation<'tcx> { diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 9cc5c6a2ee940..791e87735f40b 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -29,9 +29,7 @@ use provenance_map::*; pub use init_mask::{InitChunk, InitChunkIter}; /// Functionality required for the bytes of an `Allocation`. -pub trait AllocBytes: - Clone + fmt::Debug + Eq + PartialEq + Hash + Deref + DerefMut -{ +pub trait AllocBytes: Clone + fmt::Debug + Deref + DerefMut { /// Create an `AllocBytes` from a slice of `u8`. fn from_bytes<'a>(slice: impl Into>, _align: Align) -> Self; @@ -346,10 +344,10 @@ impl Allocation { } } -impl Allocation { +impl Allocation { /// Adjust allocation from the ones in `tcx` to a custom Machine instance - /// with a different `Provenance` and `Extra` type. - pub fn adjust_from_tcx( + /// with a different `Provenance`, `Extra` and `Byte` type. + pub fn adjust_from_tcx( self, cx: &impl HasDataLayout, extra: Extra, @@ -371,7 +369,7 @@ impl Allocation { } // Create allocation. Ok(Allocation { - bytes, + bytes: AllocBytes::from_bytes(Cow::Owned(Vec::from(bytes)), self.align), provenance: ProvenanceMap::from_presorted_ptrs(new_provenance), init_mask: self.init_mask, align: self.align, diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index b2400cec42f16..3dc55509dad9d 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -1,8 +1,9 @@ use crate::traits::query::evaluate_obligation::InferCtxtExt as _; -use crate::traits::{self, ObligationCtxt, SelectionContext, TraitEngineExt as _}; +use crate::traits::{self, ObligationCtxt, SelectionContext}; + use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; -use rustc_infer::traits::{Obligation, TraitEngine, TraitEngineExt as _}; +use rustc_infer::traits::Obligation; use rustc_macros::extension; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryResponse}; @@ -93,9 +94,9 @@ impl<'tcx> InferCtxt<'tcx> { ty::TraitRef::new(self.tcx, trait_def_id, [ty]), )) { Ok(Some(selection)) => { - let mut fulfill_cx = >::new(self); - fulfill_cx.register_predicate_obligations(self, selection.nested_obligations()); - Some(fulfill_cx.select_all_or_error(self)) + let ocx = ObligationCtxt::new(self); + ocx.register_obligations(selection.nested_obligations()); + Some(ocx.select_all_or_error()) } Ok(None) | Err(_) => None, } diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 7c6dd4d3febc9..97de25295b813 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -14,7 +14,6 @@ use rustc_ast_ir::visit::VisitorResult; use rustc_infer::infer::resolve::EagerResolver; use rustc_infer::infer::type_variable::TypeVariableOrigin; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; -use rustc_infer::traits::{TraitEngine, TraitEngineExt}; use rustc_macros::extension; use rustc_middle::infer::unify_key::ConstVariableOrigin; use rustc_middle::traits::query::NoSolution; @@ -26,9 +25,9 @@ use rustc_middle::ty::TypeFoldable; use rustc_span::{Span, DUMMY_SP}; use crate::solve::eval_ctxt::canonical; -use crate::solve::FulfillmentCtxt; use crate::solve::{EvalCtxt, GoalEvaluationKind, GoalSource}; use crate::solve::{GenerateProofTree, InferCtxtEvalExt}; +use crate::traits::ObligationCtxt; pub struct InspectConfig { pub max_depth: usize, @@ -74,14 +73,13 @@ impl<'tcx> NormalizesToTermHack<'tcx> { .eq(DefineOpaqueTypes::Yes, self.term, self.unconstrained_term) .map_err(|_| NoSolution) .and_then(|InferOk { value: (), obligations }| { - let mut fulfill_cx = FulfillmentCtxt::new(infcx); - fulfill_cx.register_predicate_obligations(infcx, obligations); - if fulfill_cx.select_where_possible(infcx).is_empty() { - if fulfill_cx.pending_obligations().is_empty() { - Ok(Certainty::Yes) - } else { - Ok(Certainty::AMBIGUOUS) - } + let ocx = ObligationCtxt::new(infcx); + ocx.register_obligations(obligations); + let errors = ocx.select_all_or_error(); + if errors.is_empty() { + Ok(Certainty::Yes) + } else if errors.iter().all(|e| !e.is_true_error()) { + Ok(Certainty::AMBIGUOUS) } else { Err(NoSolution) } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 86e7c42376aa0..59725ce9de096 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -6,12 +6,9 @@ use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::InferOk; -use crate::regions::InferCtxtRegionExt; use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor}; -use crate::solve::{deeply_normalize_for_diagnostics, inspect, FulfillmentCtxt}; -use crate::traits::engine::TraitEngineExt as _; +use crate::solve::{deeply_normalize_for_diagnostics, inspect}; use crate::traits::select::IntercrateAmbiguityCause; -use crate::traits::structural_normalize::StructurallyNormalizeExt; use crate::traits::NormalizeExt; use crate::traits::SkipLeakCheck; use crate::traits::{ @@ -22,7 +19,7 @@ use rustc_errors::{Diag, EmissionGuarantee}; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::{util, FulfillmentErrorCode, TraitEngine, TraitEngineExt}; +use rustc_infer::traits::{util, FulfillmentErrorCode}; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal}; use rustc_middle::traits::specialization_graph::OverlapMode; @@ -35,6 +32,7 @@ use std::fmt::Debug; use std::ops::ControlFlow; use super::error_reporting::suggest_new_overflow_limit; +use super::ObligationCtxt; /// Whether we do the orphan check relative to this crate or to some remote crate. #[derive(Copy, Clone, Debug)] @@ -361,23 +359,27 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>( let infcx = selcx.infcx; if infcx.next_trait_solver() { - let mut fulfill_cx = FulfillmentCtxt::new(infcx); - fulfill_cx.register_predicate_obligations(infcx, obligations.iter().cloned()); - + let ocx = ObligationCtxt::new(infcx); + ocx.register_obligations(obligations.iter().cloned()); + let errors_and_ambiguities = ocx.select_all_or_error(); // We only care about the obligations that are *definitely* true errors. // Ambiguities do not prove the disjointness of two impls. - let errors = fulfill_cx.select_where_possible(infcx); + let (errors, ambiguities): (Vec<_>, Vec<_>) = + errors_and_ambiguities.into_iter().partition(|error| error.is_true_error()); + if errors.is_empty() { - let overflow_errors = fulfill_cx.collect_remaining_errors(infcx); - let overflowing_predicates = overflow_errors - .into_iter() - .filter(|e| match e.code { - FulfillmentErrorCode::Ambiguity { overflow: Some(true) } => true, - _ => false, - }) - .map(|e| infcx.resolve_vars_if_possible(e.obligation.predicate)) - .collect(); - IntersectionHasImpossibleObligations::No { overflowing_predicates } + IntersectionHasImpossibleObligations::No { + overflowing_predicates: ambiguities + .into_iter() + .filter(|error| { + matches!( + error.code, + FulfillmentErrorCode::Ambiguity { overflow: Some(true) } + ) + }) + .map(|e| infcx.resolve_vars_if_possible(e.obligation.predicate)) + .collect(), + } } else { IntersectionHasImpossibleObligations::Yes } @@ -589,13 +591,14 @@ fn try_prove_negated_where_clause<'tcx>( // Without this, we over-eagerly register coherence ambiguity candidates when // impl candidates do exist. let ref infcx = root_infcx.fork_with_intercrate(false); - let mut fulfill_cx = FulfillmentCtxt::new(infcx); - - fulfill_cx.register_predicate_obligation( - infcx, - Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, negative_predicate), - ); - if !fulfill_cx.select_all_or_error(infcx).is_empty() { + let ocx = ObligationCtxt::new(infcx); + ocx.register_obligation(Obligation::new( + infcx.tcx, + ObligationCause::dummy(), + param_env, + negative_predicate, + )); + if !ocx.select_all_or_error().is_empty() { return false; } @@ -603,8 +606,7 @@ fn try_prove_negated_where_clause<'tcx>( // if that wasn't implemented just for LocalDefId, and we'd need to do // the normalization ourselves since this is totally fallible... let outlives_env = OutlivesEnvironment::new(param_env); - - let errors = infcx.resolve_regions(&outlives_env); + let errors = ocx.resolve_regions(&outlives_env); if !errors.is_empty() { return false; } @@ -1129,22 +1131,17 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { result: Ok(_), } = cand.kind() { - let lazily_normalize_ty = |ty: Ty<'tcx>| { - let mut fulfill_cx = >::new(infcx); + let lazily_normalize_ty = |mut ty: Ty<'tcx>| { if matches!(ty.kind(), ty::Alias(..)) { - // FIXME(-Znext-solver=coherence): we currently don't - // normalize opaque types here, resulting in diverging behavior - // for TAITs. - match infcx - .at(&ObligationCause::dummy(), param_env) - .structurally_normalize(ty, &mut *fulfill_cx) - { - Ok(ty) => Ok(ty), - Err(_errs) => Err(()), + let ocx = ObligationCtxt::new(infcx); + ty = ocx + .structurally_normalize(&ObligationCause::dummy(), param_env, ty) + .map_err(|_| ())?; + if !ocx.select_where_possible().is_empty() { + return Err(()); } - } else { - Ok(ty) } + Ok(ty) }; infcx.probe(|_| { diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 432d51ff8f90b..551c8e7702ef7 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -7,6 +7,7 @@ use crate::regions::InferCtxtRegionExt; use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt; use crate::traits::error_reporting::TypeErrCtxtExt; use crate::traits::NormalizeExt; +use crate::traits::StructurallyNormalizeExt; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -15,6 +16,7 @@ use rustc_infer::infer::canonical::{ Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse, }; use rustc_infer::infer::outlives::env::OutlivesEnvironment; +use rustc_infer::infer::RegionResolutionError; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; use rustc_infer::traits::{ FulfillmentError, Obligation, ObligationCause, PredicateObligation, TraitEngineExt as _, @@ -117,6 +119,17 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { self.infcx.at(cause, param_env).deeply_normalize(value, &mut **self.engine.borrow_mut()) } + pub fn structurally_normalize( + &self, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + value: Ty<'tcx>, + ) -> Result, Vec>> { + self.infcx + .at(cause, param_env) + .structurally_normalize(value, &mut **self.engine.borrow_mut()) + } + pub fn eq>( &self, cause: &ObligationCause<'tcx>, @@ -182,6 +195,18 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { self.engine.borrow_mut().select_all_or_error(self.infcx) } + /// Returns the not-yet-processed and stalled obligations from the + /// `ObligationCtxt`. + /// + /// Takes ownership of the context as doing operations such as + /// [`ObligationCtxt::eq`] afterwards will result in other obligations + /// getting ignored. You can make a new `ObligationCtxt` if this + /// needs to be done in a loop, for example. + #[must_use] + pub fn into_pending_obligations(self) -> Vec> { + self.engine.borrow().pending_obligations() + } + /// Resolves regions and reports errors. /// /// Takes ownership of the context as doing trait solving afterwards @@ -199,6 +224,18 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { } } + /// Resolves regions and reports errors. + /// + /// Takes ownership of the context as doing trait solving afterwards + /// will result in region constraints getting ignored. + #[must_use] + pub fn resolve_regions( + self, + outlives_env: &OutlivesEnvironment<'tcx>, + ) -> Vec> { + self.infcx.resolve_regions(outlives_env) + } + pub fn assumed_wf_types_and_report_errors( &self, param_env: ty::ParamEnv<'tcx>, 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 5f2a894413529..87d240cf8ac75 100644 --- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs +++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs @@ -1,9 +1,10 @@ -use rustc_infer::traits::{TraitEngine, TraitEngineExt}; use rustc_macros::extension; use crate::infer::canonical::OriginalQueryValues; use crate::infer::InferCtxt; -use crate::traits::{EvaluationResult, OverflowError, PredicateObligation, SelectionContext}; +use crate::traits::{ + EvaluationResult, ObligationCtxt, OverflowError, PredicateObligation, SelectionContext, +}; #[extension(pub trait InferCtxtExt<'tcx>)] impl<'tcx> InferCtxt<'tcx> { @@ -67,21 +68,22 @@ impl<'tcx> InferCtxt<'tcx> { if self.next_trait_solver() { self.probe(|snapshot| { - let mut fulfill_cx = crate::solve::FulfillmentCtxt::new(self); - fulfill_cx.register_predicate_obligation(self, obligation.clone()); - // True errors - // FIXME(-Znext-solver): Overflows are reported as ambig here, is that OK? - if !fulfill_cx.select_where_possible(self).is_empty() { - Ok(EvaluationResult::EvaluatedToErr) - } else if !fulfill_cx.select_all_or_error(self).is_empty() { - Ok(EvaluationResult::EvaluatedToAmbig) - } else if self.opaque_types_added_in_snapshot(snapshot) { - Ok(EvaluationResult::EvaluatedToOkModuloOpaqueTypes) + let ocx = ObligationCtxt::new(self); + ocx.register_obligation(obligation.clone()); + let mut result = EvaluationResult::EvaluatedToOk; + for error in ocx.select_all_or_error() { + if error.is_true_error() { + return Ok(EvaluationResult::EvaluatedToErr); + } else { + result = result.max(EvaluationResult::EvaluatedToAmbig); + } + } + if self.opaque_types_added_in_snapshot(snapshot) { + result = result.max(EvaluationResult::EvaluatedToOkModuloOpaqueTypes); } else if self.region_constraints_added_in_snapshot(snapshot) { - Ok(EvaluationResult::EvaluatedToOkModuloRegions) - } else { - Ok(EvaluationResult::EvaluatedToOk) + result = result.max(EvaluationResult::EvaluatedToOkModuloRegions); } + Ok(result) }) } else { assert!(!self.intercrate); diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index 51f38964415b0..b96b1b67a7407 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -4,14 +4,13 @@ // general routines. use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::{FulfillmentErrorCode, TraitEngineExt as _}; +use rustc_infer::traits::FulfillmentErrorCode; use rustc_middle::bug; use rustc_middle::traits::CodegenObligationError; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::{ - ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, TraitEngineExt, - Unimplemented, + ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext, Unimplemented, }; use tracing::debug; @@ -51,15 +50,15 @@ pub fn codegen_select_candidate<'tcx>( // Currently, we use a fulfillment context to completely resolve // all nested obligations. This is because they can inform the // inference of the impl's type parameters. - let mut fulfill_cx = >::new(&infcx); - let impl_source = selection.map(|predicate| { - fulfill_cx.register_predicate_obligation(&infcx, predicate); + let ocx = ObligationCtxt::new(&infcx); + let impl_source = selection.map(|obligation| { + ocx.register_obligation(obligation); }); // In principle, we only need to do this so long as `impl_source` // contains unbound type parameters. It could be a slight // optimization to stop iterating early. - let errors = fulfill_cx.select_all_or_error(&infcx); + let errors = ocx.select_all_or_error(); if !errors.is_empty() { // `rustc_monomorphize::collector` assumes there are no type errors. // Cycle errors are the only post-monomorphization errors possible; emit them now so diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index d2006dfc12b55..32cdd13fbebda 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -860,6 +860,7 @@ impl Drop for Dir { target_os = "hurd", target_os = "espidf", target_os = "fuchsia", + target_os = "horizon", )))] { let fd = unsafe { libc::dirfd(self.0) }; diff --git a/rustfmt.toml b/rustfmt.toml index 0b0674af8b4a0..67219b15d203d 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -13,7 +13,7 @@ ignore = [ # tests for now are not formatted, as they are sometimes pretty-printing constrained # (and generally rustfmt can move around comments in UI-testing incompatible ways) - "/tests/", + "!/tests/run-make/*/rmake.rs", # do not format submodules # FIXME: sync submodule list with tidy/bootstrap/etc diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 9fc65a0a73a10..d9dc34c013700 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -115,7 +115,11 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { let rustfmt_config: RustfmtConfig = t!(toml::from_str(&rustfmt_config)); let mut fmt_override = ignore::overrides::OverrideBuilder::new(&build.src); for ignore in rustfmt_config.ignore { - fmt_override.add(&format!("!{ignore}")).expect(&ignore); + if let Some(ignore) = ignore.strip_prefix('!') { + fmt_override.add(ignore).expect(ignore); + } else { + fmt_override.add(&format!("!{ignore}")).expect(&ignore); + } } let git_available = match Command::new("git") .arg("--version") diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 6ccf29fb6cbef..0c069a540696f 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -26,6 +26,17 @@ pub struct Finder { path: OsString, } +// During sanity checks, we search for target names to determine if they exist in the compiler's built-in +// target list (`rustc --print target-list`). While a target name may be present in the stage2 compiler, +// it might not yet be included in stage0. In such cases, we handle the targets missing from stage0 in this list. +// +// Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap). +const STAGE0_MISSING_TARGETS: &[&str] = &[ + // just a dummy comment so the list doesn't get onelined + "aarch64-apple-visionos", + "aarch64-apple-visionos-sim", +]; + impl Finder { pub fn new() -> Self { Self { cache: HashMap::new(), path: env::var_os("PATH").unwrap_or_default() } @@ -178,32 +189,40 @@ than building it. continue; } - // Check if there exists a built-in target in the list of supported targets. - let mut has_target = false; let target_str = target.to_string(); - let supported_target_list = - output(Command::new(&build.config.initial_rustc).args(["--print", "target-list"])); + // Ignore fake targets that are only used for unit tests in bootstrap. + if !["A", "B", "C"].contains(&target_str.as_str()) { + let mut has_target = false; + + let supported_target_list = + output(Command::new(&build.config.initial_rustc).args(["--print", "target-list"])); + + // Check if it's a built-in target. + has_target |= supported_target_list.contains(&target_str); + has_target |= STAGE0_MISSING_TARGETS.contains(&target_str.as_str()); - has_target |= supported_target_list.contains(&target_str); + if !has_target { + // This might also be a custom target, so check the target file that could have been specified by the user. + if let Some(custom_target_path) = env::var_os("RUST_TARGET_PATH") { + let mut target_filename = OsString::from(&target_str); + // Target filename ends with `.json`. + target_filename.push(".json"); - // If not, check for a valid file location that may have been specified - // by the user for the custom target. - if let Some(custom_target_path) = env::var_os("RUST_TARGET_PATH") { - let mut target_os_str = OsString::from(&target_str); - target_os_str.push(".json"); - // Recursively traverse through nested directories. - let walker = WalkDir::new(custom_target_path).into_iter(); - for entry in walker.filter_map(|e| e.ok()) { - has_target |= entry.file_name() == target_os_str; + // Recursively traverse through nested directories. + let walker = WalkDir::new(custom_target_path).into_iter(); + for entry in walker.filter_map(|e| e.ok()) { + has_target |= entry.file_name() == target_filename; + } + } } - } - if !has_target && !["A", "B", "C"].contains(&target_str.as_str()) { - panic!( - "No such target exists in the target list, + if !has_target { + panic!( + "No such target exists in the target list, specify a correct location of the JSON specification file for custom targets!" - ); + ); + } } if !build.config.dry_run() { diff --git a/src/tools/run-make-support/src/cc.rs b/src/tools/run-make-support/src/cc.rs index 146123793be40..4082639f618a1 100644 --- a/src/tools/run-make-support/src/cc.rs +++ b/src/tools/run-make-support/src/cc.rs @@ -71,6 +71,11 @@ impl Cc { self } + + /// Get the [`Output`][::std::process::Output] of the finished process. + pub fn output(&mut self) -> ::std::process::Output { + self.cmd.output().expect("failed to get output of finished process") + } } /// `EXTRACFLAGS` diff --git a/src/tools/run-make-support/src/clang.rs b/src/tools/run-make-support/src/clang.rs index ed9f8383dc3ae..c30ba29ed76d6 100644 --- a/src/tools/run-make-support/src/clang.rs +++ b/src/tools/run-make-support/src/clang.rs @@ -70,4 +70,9 @@ impl Clang { self.cmd.arg(format!("-fuse-ld={ld}")); self } + + /// Get the [`Output`][::std::process::Output] of the finished process. + pub fn output(&mut self) -> ::std::process::Output { + self.cmd.output().expect("failed to get output of finished process") + } } diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index a874c1313b510..239f90b23c981 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -144,7 +144,7 @@ pub fn set_host_rpath(cmd: &mut Command) { } /// Implement common helpers for command wrappers. This assumes that the command wrapper is a struct -/// containing a `cmd: Command` field. The provided helpers are: +/// containing a `cmd: Command` field and a `output` function. The provided helpers are: /// /// 1. Generic argument acceptors: `arg` and `args` (delegated to [`Command`]). These are intended /// to be *fallback* argument acceptors, when specific helpers don't make sense. Prefer to add @@ -160,7 +160,12 @@ pub fn set_host_rpath(cmd: &mut Command) { /// Example usage: /// /// ```ignore (illustrative) -/// struct CommandWrapper { cmd: Command } +/// struct CommandWrapper { cmd: Command } // <- required `cmd` field +/// +/// impl CommandWrapper { +/// /// Get the [`Output`][::std::process::Output] of the finished process. +/// pub fn output(&mut self) -> Output { /* ... */ } // <- required `output()` method +/// } /// /// crate::impl_common_helpers!(CommandWrapper); /// @@ -231,18 +236,13 @@ macro_rules! impl_common_helpers { self } - /// Get the [`Output`][::std::process::Output] of the finished process. - pub fn output(&mut self) -> ::std::process::Output { - self.cmd.output().expect("failed to get output of finished process") - } - /// Run the constructed command and assert that it is successfully run. #[track_caller] pub fn run(&mut self) -> ::std::process::Output { let caller_location = ::std::panic::Location::caller(); let caller_line_number = caller_location.line(); - let output = self.cmd.output().unwrap(); + let output = self.output(); if !output.status.success() { handle_failed_output(&self.cmd, output, caller_line_number); } @@ -255,7 +255,7 @@ macro_rules! impl_common_helpers { let caller_location = ::std::panic::Location::caller(); let caller_line_number = caller_location.line(); - let output = self.cmd.output().unwrap(); + let output = self.output(); if output.status.success() { handle_failed_output(&self.cmd, output, caller_line_number); } diff --git a/src/tools/run-make-support/src/llvm_readobj.rs b/src/tools/run-make-support/src/llvm_readobj.rs index 32ea07e932ed8..4e1f2b002f301 100644 --- a/src/tools/run-make-support/src/llvm_readobj.rs +++ b/src/tools/run-make-support/src/llvm_readobj.rs @@ -41,4 +41,10 @@ impl LlvmReadobj { self.cmd.arg("--file-header"); self } + + /// Get the [`Output`][::std::process::Output] of the finished process. + #[track_caller] + pub fn output(&mut self) -> ::std::process::Output { + self.cmd.output().expect("failed to get output of finished process") + } } diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs index ddaae3236c2b5..37539528ab3fc 100644 --- a/src/tools/run-make-support/src/rustc.rs +++ b/src/tools/run-make-support/src/rustc.rs @@ -1,7 +1,8 @@ use std::env; use std::ffi::OsString; +use std::io::Write; use std::path::Path; -use std::process::{Command, Output}; +use std::process::{Command, Output, Stdio}; use crate::{handle_failed_output, set_host_rpath, tmp_dir}; @@ -19,6 +20,7 @@ pub fn aux_build() -> Rustc { #[derive(Debug)] pub struct Rustc { cmd: Command, + stdin: Option>, } crate::impl_common_helpers!(Rustc); @@ -37,14 +39,14 @@ impl Rustc { /// Construct a new `rustc` invocation. pub fn new() -> Self { let cmd = setup_common(); - Self { cmd } + Self { cmd, stdin: None } } /// Construct a new `rustc` invocation with `aux_build` preset (setting `--crate-type=lib`). pub fn new_aux_build() -> Self { let mut cmd = setup_common(); cmd.arg("--crate-type=lib"); - Self { cmd } + Self { cmd, stdin: None } } // Argument provider methods @@ -161,12 +163,40 @@ impl Rustc { self } + /// Specify a stdin input + pub fn stdin>(&mut self, input: I) -> &mut Self { + self.stdin = Some(input.as_ref().to_vec().into_boxed_slice()); + self + } + + /// Get the [`Output`][::std::process::Output] of the finished process. + #[track_caller] + pub fn output(&mut self) -> ::std::process::Output { + // let's make sure we piped all the input and outputs + self.cmd.stdin(Stdio::piped()); + self.cmd.stdout(Stdio::piped()); + self.cmd.stderr(Stdio::piped()); + + if let Some(input) = &self.stdin { + let mut child = self.cmd.spawn().unwrap(); + + { + let mut stdin = child.stdin.take().unwrap(); + stdin.write_all(input.as_ref()).unwrap(); + } + + child.wait_with_output().expect("failed to get output of finished process") + } else { + self.cmd.output().expect("failed to get output of finished process") + } + } + #[track_caller] pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output { let caller_location = std::panic::Location::caller(); let caller_line_number = caller_location.line(); - let output = self.cmd.output().unwrap(); + let output = self.output(); if output.status.code().unwrap() != code { handle_failed_output(&self.cmd, output, caller_line_number); } diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/rustdoc.rs index 1054ac83c103c..c2c4f2e68e2f8 100644 --- a/src/tools/run-make-support/src/rustdoc.rs +++ b/src/tools/run-make-support/src/rustdoc.rs @@ -1,6 +1,7 @@ use std::env; +use std::io::Write; use std::path::Path; -use std::process::{Command, Output}; +use std::process::{Command, Output, Stdio}; use crate::{handle_failed_output, set_host_rpath}; @@ -17,6 +18,7 @@ pub fn rustdoc() -> Rustdoc { #[derive(Debug)] pub struct Rustdoc { cmd: Command, + stdin: Option>, } crate::impl_common_helpers!(Rustdoc); @@ -32,7 +34,7 @@ impl Rustdoc { /// Construct a bare `rustdoc` invocation. pub fn bare() -> Self { let cmd = setup_common(); - Self { cmd } + Self { cmd, stdin: None } } /// Construct a `rustdoc` invocation with `-L $(TARGET_RPATH_DIR)` set. @@ -40,7 +42,7 @@ impl Rustdoc { let mut cmd = setup_common(); let target_rpath_dir = env::var_os("TARGET_RPATH_DIR").unwrap(); cmd.arg(format!("-L{}", target_rpath_dir.to_string_lossy())); - Self { cmd } + Self { cmd, stdin: None } } /// Specify path to the input file. @@ -62,12 +64,41 @@ impl Rustdoc { self } + /// Specify a stdin input + pub fn stdin>(&mut self, input: I) -> &mut Self { + self.cmd.stdin(Stdio::piped()); + self.stdin = Some(input.as_ref().to_vec().into_boxed_slice()); + self + } + + /// Get the [`Output`][::std::process::Output] of the finished process. + #[track_caller] + pub fn output(&mut self) -> ::std::process::Output { + // let's make sure we piped all the input and outputs + self.cmd.stdin(Stdio::piped()); + self.cmd.stdout(Stdio::piped()); + self.cmd.stderr(Stdio::piped()); + + if let Some(input) = &self.stdin { + let mut child = self.cmd.spawn().unwrap(); + + { + let mut stdin = child.stdin.take().unwrap(); + stdin.write_all(input.as_ref()).unwrap(); + } + + child.wait_with_output().expect("failed to get output of finished process") + } else { + self.cmd.output().expect("failed to get output of finished process") + } + } + #[track_caller] pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output { let caller_location = std::panic::Location::caller(); let caller_line_number = caller_location.line(); - let output = self.cmd.output().unwrap(); + let output = self.output(); if output.status.code().unwrap() != code { handle_failed_output(&self.cmd, output, caller_line_number); } diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 69c6dda4b19cf..4b79b910ec39c 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -288,7 +288,6 @@ run-make/static-unwinding/Makefile run-make/staticlib-blank-lib/Makefile run-make/staticlib-dylib-linkage/Makefile run-make/std-core-cycle/Makefile -run-make/stdin-non-utf8/Makefile run-make/suspicious-library/Makefile run-make/symbol-mangling-hashed/Makefile run-make/symbol-visibility/Makefile diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs index fe0ceaf6b043d..4b7ce4e57d57c 100644 --- a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs +++ b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs @@ -5,7 +5,7 @@ use std::path::PathBuf; -use run_make_support::{rustc, aux_build}; +use run_make_support::{aux_build, rustc}; fn main() { aux_build().input("stable.rs").emit("metadata").run(); @@ -13,11 +13,7 @@ fn main() { let mut stable_path = PathBuf::from(env!("TMPDIR")); stable_path.push("libstable.rmeta"); - let output = rustc() - .input("main.rs") - .emit("metadata") - .extern_("stable", &stable_path) - .output(); + let output = rustc().input("main.rs").emit("metadata").extern_("stable", &stable_path).output(); let stderr = String::from_utf8_lossy(&output.stderr); let version = include_str!(concat!(env!("S"), "/src/version")); diff --git a/tests/run-make/compiler-builtins/rmake.rs b/tests/run-make/compiler-builtins/rmake.rs index 1784784845995..f5da50ebb043b 100644 --- a/tests/run-make/compiler-builtins/rmake.rs +++ b/tests/run-make/compiler-builtins/rmake.rs @@ -49,22 +49,22 @@ fn main() { let bootstrap_cargo = std::env::var("BOOTSTRAP_CARGO").unwrap(); let mut cmd = std::process::Command::new(bootstrap_cargo); cmd.args([ - "build", - "--manifest-path", - manifest_path.to_str().unwrap(), - "-Zbuild-std=core", - "--target", - &target, - ]) - .env_clear() - .env("PATH", path) - .env("RUSTC", rustc) - .env("RUSTFLAGS", "-Copt-level=0 -Cdebug-assertions=yes") - .env("CARGO_TARGET_DIR", &target_dir) - .env("RUSTC_BOOTSTRAP", "1") - // Visual Studio 2022 requires that the LIB env var be set so it can - // find the Windows SDK. - .env("LIB", std::env::var("LIB").unwrap_or_default()); + "build", + "--manifest-path", + manifest_path.to_str().unwrap(), + "-Zbuild-std=core", + "--target", + &target, + ]) + .env_clear() + .env("PATH", path) + .env("RUSTC", rustc) + .env("RUSTFLAGS", "-Copt-level=0 -Cdebug-assertions=yes") + .env("CARGO_TARGET_DIR", &target_dir) + .env("RUSTC_BOOTSTRAP", "1") + // Visual Studio 2022 requires that the LIB env var be set so it can + // find the Windows SDK. + .env("LIB", std::env::var("LIB").unwrap_or_default()); set_host_rpath(&mut cmd); let status = cmd.status().unwrap(); diff --git a/tests/run-make/exit-code/rmake.rs b/tests/run-make/exit-code/rmake.rs index f4ceabe126cbf..b1143153d0af0 100644 --- a/tests/run-make/exit-code/rmake.rs +++ b/tests/run-make/exit-code/rmake.rs @@ -3,17 +3,11 @@ use run_make_support::{rustc, rustdoc, tmp_dir}; fn main() { - rustc() - .arg("success.rs") - .run(); + rustc().arg("success.rs").run(); - rustc() - .arg("--invalid-arg-foo") - .run_fail_assert_exit_code(1); + rustc().arg("--invalid-arg-foo").run_fail_assert_exit_code(1); - rustc() - .arg("compile-error.rs") - .run_fail_assert_exit_code(1); + rustc().arg("compile-error.rs").run_fail_assert_exit_code(1); rustc() .env("RUSTC_ICE", "0") @@ -21,21 +15,11 @@ fn main() { .arg("compile-error.rs") .run_fail_assert_exit_code(101); - rustdoc() - .arg("success.rs") - .arg("-o") - .arg(tmp_dir().join("exit-code")) - .run(); + rustdoc().arg("success.rs").arg("-o").arg(tmp_dir().join("exit-code")).run(); - rustdoc() - .arg("--invalid-arg-foo") - .run_fail_assert_exit_code(1); + rustdoc().arg("--invalid-arg-foo").run_fail_assert_exit_code(1); - rustdoc() - .arg("compile-error.rs") - .run_fail_assert_exit_code(1); + rustdoc().arg("compile-error.rs").run_fail_assert_exit_code(1); - rustdoc() - .arg("lint-failure.rs") - .run_fail_assert_exit_code(1); + rustdoc().arg("lint-failure.rs").run_fail_assert_exit_code(1); } diff --git a/tests/run-make/print-native-static-libs/rmake.rs b/tests/run-make/print-native-static-libs/rmake.rs index 5249920cc60e5..edb85d568c678 100644 --- a/tests/run-make/print-native-static-libs/rmake.rs +++ b/tests/run-make/print-native-static-libs/rmake.rs @@ -14,15 +14,11 @@ use std::io::BufRead; -use run_make_support::{rustc, is_msvc}; +use run_make_support::{is_msvc, rustc}; fn main() { // build supporting crate - rustc() - .input("bar.rs") - .crate_type("rlib") - .arg("-lbar_cli") - .run(); + rustc().input("bar.rs").crate_type("rlib").arg("-lbar_cli").run(); // build main crate as staticlib let output = rustc() @@ -37,7 +33,9 @@ fn main() { for l in output.stderr.lines() { let l = l.expect("utf-8 string"); - let Some(args) = l.strip_prefix("note: native-static-libs:") else { continue; }; + let Some(args) = l.strip_prefix("note: native-static-libs:") else { + continue; + }; assert!(!found_note); found_note = true; @@ -53,11 +51,11 @@ fn main() { ); let found = $args.contains(&&*lib); assert!(found, "unable to find lib `{}` in those linker args: {:?}", lib, $args); - }} + }}; } assert_contains_lib!("glib-2.0" in args); // in bar.rs - assert_contains_lib!("systemd" in args); // in foo.rs + assert_contains_lib!("systemd" in args); // in foo.rs assert_contains_lib!("bar_cli" in args); assert_contains_lib!("foo_cli" in args); diff --git a/tests/run-make/print-to-output/rmake.rs b/tests/run-make/print-to-output/rmake.rs index f710d0dc3c9b5..1763cd378d2d9 100644 --- a/tests/run-make/print-to-output/rmake.rs +++ b/tests/run-make/print-to-output/rmake.rs @@ -13,11 +13,7 @@ struct Option<'a> { fn main() { // Printed from CodegenBackend trait impl in rustc_codegen_llvm/src/lib.rs - check(Option { - target: &target(), - option: "relocation-models", - includes: &["dynamic-no-pic"], - }); + check(Option { target: &target(), option: "relocation-models", includes: &["dynamic-no-pic"] }); // Printed by compiler/rustc_codegen_llvm/src/llvm_util.rs check(Option { diff --git a/tests/run-make/stdin-non-utf8/Makefile b/tests/run-make/stdin-non-utf8/Makefile deleted file mode 100644 index 709d4cf140895..0000000000000 --- a/tests/run-make/stdin-non-utf8/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -include ../tools.mk - -all: - cp non-utf8 $(TMPDIR)/non-utf.rs - cat $(TMPDIR)/non-utf.rs | $(RUSTC) - 2>&1 \ - | $(CGREP) "error: couldn't read from stdin, as it did not contain valid UTF-8" diff --git a/tests/run-make/stdin-non-utf8/non-utf8 b/tests/run-make/stdin-non-utf8/non-utf8 deleted file mode 100644 index bc87051a85299..0000000000000 --- a/tests/run-make/stdin-non-utf8/non-utf8 +++ /dev/null @@ -1 +0,0 @@ -Ò diff --git a/tests/run-make/stdin-rustc/rmake.rs b/tests/run-make/stdin-rustc/rmake.rs new file mode 100644 index 0000000000000..c07a6df4d84a2 --- /dev/null +++ b/tests/run-make/stdin-rustc/rmake.rs @@ -0,0 +1,26 @@ +//! This test checks rustc `-` (stdin) support + +use run_make_support::{is_windows, rustc, tmp_dir}; + +const HELLO_WORLD: &str = r#" +fn main() { + println!("Hello world!"); +} +"#; + +const NOT_UTF8: &[u8] = &[0xff, 0xff, 0xff]; + +fn main() { + let out_dir = tmp_dir(); + + // echo $HELLO_WORLD | rustc - + rustc().arg("-").stdin(HELLO_WORLD).run(); + assert!( + out_dir.join(if !is_windows() { "rust_out" } else { "rust_out.exe" }).try_exists().unwrap() + ); + + // echo $NOT_UTF8 | rustc - + let output = rustc().arg("-").stdin(NOT_UTF8).run_fail(); + let stderr = String::from_utf8(output.stderr).unwrap(); + assert!(stderr.contains("error: couldn't read from stdin, as it did not contain valid UTF-8")); +} diff --git a/tests/run-make/wasm-custom-sections-opt/rmake.rs b/tests/run-make/wasm-custom-sections-opt/rmake.rs index 24570d8baf5a6..50916b1bf815a 100644 --- a/tests/run-make/wasm-custom-sections-opt/rmake.rs +++ b/tests/run-make/wasm-custom-sections-opt/rmake.rs @@ -1,6 +1,6 @@ //@ only-wasm32-wasip1 -use run_make_support::{tmp_dir, wasmparser, rustc}; +use run_make_support::{rustc, tmp_dir, wasmparser}; use std::collections::HashMap; use std::path::Path; diff --git a/tests/run-make/wasm-export-all-symbols/rmake.rs b/tests/run-make/wasm-export-all-symbols/rmake.rs index 50c99d027d5ac..f4c51bc4ab418 100644 --- a/tests/run-make/wasm-export-all-symbols/rmake.rs +++ b/tests/run-make/wasm-export-all-symbols/rmake.rs @@ -1,6 +1,6 @@ //@ only-wasm32-wasip1 -use run_make_support::{tmp_dir, wasmparser, rustc}; +use run_make_support::{rustc, tmp_dir, wasmparser}; use std::collections::HashMap; use std::path::Path; use wasmparser::ExternalKind::*; diff --git a/tests/run-make/wasm-import-module/rmake.rs b/tests/run-make/wasm-import-module/rmake.rs index 333d0df4653fa..6eed229e90789 100644 --- a/tests/run-make/wasm-import-module/rmake.rs +++ b/tests/run-make/wasm-import-module/rmake.rs @@ -1,17 +1,12 @@ //@ only-wasm32-wasip1 -use run_make_support::{tmp_dir, wasmparser, rustc}; +use run_make_support::{rustc, tmp_dir, wasmparser}; use std::collections::HashMap; use wasmparser::TypeRef::Func; fn main() { rustc().input("foo.rs").target("wasm32-wasip1").run(); - rustc() - .input("bar.rs") - .target("wasm32-wasip1") - .arg("-Clto") - .opt() - .run(); + rustc().input("bar.rs").target("wasm32-wasip1").arg("-Clto").opt().run(); let file = std::fs::read(&tmp_dir().join("bar.wasm")).unwrap();