Auto merge of #124660 - matthiaskrgr:rollup-j8bfzfn, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #124461 (handle the targets that are missing in stage0) - #124492 (Generalize `adjust_from_tcx` for `Allocation`) - #124588 (Use `ObligationCtxt` in favor of `TraitEngine` in many more places) - #124612 (Add support for inputing via stdin with run-make-support) - #124613 (Allow fmt to run on rmake.rs test files) - #124649 (Fix HorizonOS build broken by #124210) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
d6d3b342e8
32 changed files with 356 additions and 234 deletions
|
@ -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<traits::PredicateObligation<'tcx>>)> {
|
||||
let mut fulfill_cx = <dyn TraitEngine<'tcx>>::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,
|
||||
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).
|
||||
debug!(?errors, "encountered errors while fulfilling");
|
||||
// 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
|
||||
|
|
|
@ -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 = <dyn TraitEngine<'tcx>>::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 = <dyn TraitEngine<'tcx>>::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;
|
||||
}
|
||||
_ => {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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<Target = [u8]> + DerefMut<Target = [u8]>
|
||||
{
|
||||
pub trait AllocBytes: Clone + fmt::Debug + Deref<Target = [u8]> + DerefMut<Target = [u8]> {
|
||||
/// Create an `AllocBytes` from a slice of `u8`.
|
||||
fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align) -> Self;
|
||||
|
||||
|
@ -346,10 +344,10 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<Bytes: AllocBytes> Allocation<CtfeProvenance, (), Bytes> {
|
||||
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<Prov: Provenance, Extra, Err>(
|
||||
/// with a different `Provenance`, `Extra` and `Byte` type.
|
||||
pub fn adjust_from_tcx<Prov: Provenance, Extra, Bytes: AllocBytes, Err>(
|
||||
self,
|
||||
cx: &impl HasDataLayout,
|
||||
extra: Extra,
|
||||
|
@ -371,7 +369,7 @@ impl<Bytes: AllocBytes> Allocation<CtfeProvenance, (), Bytes> {
|
|||
}
|
||||
// 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,
|
||||
|
|
|
@ -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 = <dyn TraitEngine<'tcx>>::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,
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
ocx.register_obligations(obligations);
|
||||
let errors = ocx.select_all_or_error();
|
||||
if errors.is_empty() {
|
||||
Ok(Certainty::Yes)
|
||||
} else {
|
||||
} else if errors.iter().all(|e| !e.is_true_error()) {
|
||||
Ok(Certainty::AMBIGUOUS)
|
||||
}
|
||||
} else {
|
||||
Err(NoSolution)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
IntersectionHasImpossibleObligations::No {
|
||||
overflowing_predicates: ambiguities
|
||||
.into_iter()
|
||||
.filter(|e| match e.code {
|
||||
FulfillmentErrorCode::Ambiguity { overflow: Some(true) } => true,
|
||||
_ => false,
|
||||
.filter(|error| {
|
||||
matches!(
|
||||
error.code,
|
||||
FulfillmentErrorCode::Ambiguity { overflow: Some(true) }
|
||||
)
|
||||
})
|
||||
.map(|e| infcx.resolve_vars_if_possible(e.obligation.predicate))
|
||||
.collect();
|
||||
IntersectionHasImpossibleObligations::No { overflowing_predicates }
|
||||
.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 = <dyn TraitEngine<'tcx>>::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)
|
||||
}
|
||||
};
|
||||
|
||||
infcx.probe(|_| {
|
||||
|
|
|
@ -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<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> {
|
||||
self.infcx
|
||||
.at(cause, param_env)
|
||||
.structurally_normalize(value, &mut **self.engine.borrow_mut())
|
||||
}
|
||||
|
||||
pub fn eq<T: ToTrace<'tcx>>(
|
||||
&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<PredicateObligation<'tcx>> {
|
||||
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<RegionResolutionError<'tcx>> {
|
||||
self.infcx.resolve_regions(outlives_env)
|
||||
}
|
||||
|
||||
pub fn assumed_wf_types_and_report_errors(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
|
|
@ -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)
|
||||
} else if self.region_constraints_added_in_snapshot(snapshot) {
|
||||
Ok(EvaluationResult::EvaluatedToOkModuloRegions)
|
||||
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 {
|
||||
Ok(EvaluationResult::EvaluatedToOk)
|
||||
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) {
|
||||
result = result.max(EvaluationResult::EvaluatedToOkModuloRegions);
|
||||
}
|
||||
Ok(result)
|
||||
})
|
||||
} else {
|
||||
assert!(!self.intercrate);
|
||||
|
|
|
@ -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 = <dyn TraitEngine<'tcx>>::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
|
||||
|
|
|
@ -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) };
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -115,8 +115,12 @@ 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 {
|
||||
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")
|
||||
.stdout(Stdio::null())
|
||||
|
|
|
@ -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,33 +189,41 @@ 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();
|
||||
|
||||
// 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());
|
||||
|
||||
// If not, check for a valid file location that may have been specified
|
||||
// by the user for the custom target.
|
||||
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_os_str = OsString::from(&target_str);
|
||||
target_os_str.push(".json");
|
||||
let mut target_filename = OsString::from(&target_str);
|
||||
// Target filename ends with `.json`.
|
||||
target_filename.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;
|
||||
has_target |= entry.file_name() == target_filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !has_target && !["A", "B", "C"].contains(&target_str.as_str()) {
|
||||
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() {
|
||||
cmd_finder.must_have(build.cc(*target));
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Box<[u8]>>,
|
||||
}
|
||||
|
||||
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<I: AsRef<[u8]>>(&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);
|
||||
}
|
||||
|
|
|
@ -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<Box<[u8]>>,
|
||||
}
|
||||
|
||||
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<I: AsRef<[u8]>>(&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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,7 +51,7 @@ 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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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"
|
|
@ -1 +0,0 @@
|
|||
<EFBFBD>
|
26
tests/run-make/stdin-rustc/rmake.rs
Normal file
26
tests/run-make/stdin-rustc/rmake.rs
Normal file
|
@ -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"));
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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::*;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue