Auto merge of #112974 - matthiaskrgr:rollup-hnk7ans, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #112616 (Improve tests on targets without unwinding) - #112643 (Always register sized obligation for argument) - #112740 (Add link to rustdoc book search chapter in help popover) - #112810 (Don't ICE on unnormalized struct tail in layout computation) - #112870 (Migrate `item_bounds` to `ty::Clause`) - #112925 (Stop hiding const eval limit in external macros) - #112960 ([tests/rustdoc] Add `@files` command) - #112962 (Fix rustdoc gui tester) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
22e9fe644e
78 changed files with 581 additions and 273 deletions
|
@ -705,7 +705,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => tcx
|
||||
.explicit_item_bounds(def_id)
|
||||
.subst_iter_copied(tcx, substs)
|
||||
.find_map(find_fn_kind_from_did),
|
||||
.find_map(|(clause, span)| find_fn_kind_from_did((clause.as_predicate(), span))),
|
||||
ty::Closure(_, substs) => match substs.as_closure().kind() {
|
||||
ty::ClosureKind::Fn => Some(hir::Mutability::Not),
|
||||
ty::ClosureKind::FnMut => Some(hir::Mutability::Mut),
|
||||
|
|
|
@ -409,9 +409,7 @@ fn fn_sig_suggestion<'tcx>(
|
|||
output = if let ty::Alias(_, alias_ty) = *output.kind() {
|
||||
tcx.explicit_item_bounds(alias_ty.def_id)
|
||||
.subst_iter_copied(tcx, alias_ty.substs)
|
||||
.find_map(|(bound, _)| {
|
||||
bound.to_opt_poly_projection_pred()?.no_bound_vars()?.term.ty()
|
||||
})
|
||||
.find_map(|(bound, _)| bound.as_projection_clause()?.no_bound_vars()?.term.ty())
|
||||
.unwrap_or_else(|| {
|
||||
span_bug!(
|
||||
ident.span,
|
||||
|
|
|
@ -1086,7 +1086,7 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt
|
|||
wfcx.infcx,
|
||||
wfcx.param_env,
|
||||
wfcx.body_def_id,
|
||||
normalized_bound,
|
||||
normalized_bound.as_predicate(),
|
||||
bound_span,
|
||||
)
|
||||
});
|
||||
|
@ -1562,7 +1562,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
|
|||
self.wfcx.infcx,
|
||||
self.wfcx.param_env,
|
||||
self.wfcx.body_def_id,
|
||||
bound,
|
||||
bound.as_predicate(),
|
||||
bound_span,
|
||||
));
|
||||
// Set the debruijn index back to innermost here, since we already eagerly
|
||||
|
|
|
@ -19,7 +19,7 @@ fn associated_type_bounds<'tcx>(
|
|||
assoc_item_def_id: LocalDefId,
|
||||
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||
span: Span,
|
||||
) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
|
||||
) -> &'tcx [(ty::Clause<'tcx>, Span)] {
|
||||
let item_ty = tcx.mk_projection(
|
||||
assoc_item_def_id.to_def_id(),
|
||||
InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
|
||||
|
@ -33,8 +33,11 @@ fn associated_type_bounds<'tcx>(
|
|||
let trait_def_id = tcx.local_parent(assoc_item_def_id);
|
||||
let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id);
|
||||
|
||||
let bounds_from_parent = trait_predicates.predicates.iter().copied().filter(|(pred, _)| {
|
||||
match pred.kind().skip_binder() {
|
||||
let bounds_from_parent = trait_predicates
|
||||
.predicates
|
||||
.iter()
|
||||
.copied()
|
||||
.filter(|(pred, _)| match pred.kind().skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr)) => tr.self_ty() == item_ty,
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) => {
|
||||
proj.projection_ty.self_ty() == item_ty
|
||||
|
@ -43,15 +46,10 @@ fn associated_type_bounds<'tcx>(
|
|||
outlives.0 == item_ty
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
});
|
||||
})
|
||||
.map(|(pred, span)| (pred.expect_clause(), span));
|
||||
|
||||
let all_bounds = tcx.arena.alloc_from_iter(
|
||||
bounds
|
||||
.clauses()
|
||||
.map(|(clause, span)| (clause.as_predicate(), span))
|
||||
.chain(bounds_from_parent),
|
||||
);
|
||||
let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses().chain(bounds_from_parent));
|
||||
debug!(
|
||||
"associated_type_bounds({}) = {:?}",
|
||||
tcx.def_path_str(assoc_item_def_id.to_def_id()),
|
||||
|
@ -71,7 +69,7 @@ fn opaque_type_bounds<'tcx>(
|
|||
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||
item_ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
|
||||
) -> &'tcx [(ty::Clause<'tcx>, Span)] {
|
||||
ty::print::with_no_queries!({
|
||||
let icx = ItemCtxt::new(tcx, opaque_def_id);
|
||||
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false));
|
||||
|
@ -79,15 +77,14 @@ fn opaque_type_bounds<'tcx>(
|
|||
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
|
||||
debug!(?bounds);
|
||||
|
||||
tcx.arena
|
||||
.alloc_from_iter(bounds.clauses().map(|(clause, span)| (clause.as_predicate(), span)))
|
||||
tcx.arena.alloc_from_iter(bounds.clauses())
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn explicit_item_bounds(
|
||||
tcx: TyCtxt<'_>,
|
||||
def_id: LocalDefId,
|
||||
) -> ty::EarlyBinder<&'_ [(ty::Predicate<'_>, Span)]> {
|
||||
) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> {
|
||||
match tcx.opt_rpitit_info(def_id.to_def_id()) {
|
||||
// RPITIT's bounds are the same as opaque type bounds, but with
|
||||
// a projection self type.
|
||||
|
@ -139,11 +136,8 @@ pub(super) fn explicit_item_bounds(
|
|||
pub(super) fn item_bounds(
|
||||
tcx: TyCtxt<'_>,
|
||||
def_id: DefId,
|
||||
) -> ty::EarlyBinder<&'_ ty::List<ty::Predicate<'_>>> {
|
||||
) -> ty::EarlyBinder<&'_ ty::List<ty::Clause<'_>>> {
|
||||
tcx.explicit_item_bounds(def_id).map_bound(|bounds| {
|
||||
tcx.mk_predicates_from_iter(util::elaborate(
|
||||
tcx,
|
||||
bounds.iter().map(|&(bound, _span)| bound),
|
||||
))
|
||||
tcx.mk_clauses_from_iter(util::elaborate(tcx, bounds.iter().map(|&(bound, _span)| bound)))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use rustc_hir as hir;
|
|||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::subst::GenericArgKind;
|
||||
use rustc_middle::ty::{self, CratePredicatesMap, TyCtxt};
|
||||
use rustc_middle::ty::{self, CratePredicatesMap, ToPredicate, TyCtxt};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
|
||||
|
@ -17,7 +17,7 @@ pub fn provide(providers: &mut Providers) {
|
|||
*providers = Providers { inferred_outlives_of, inferred_outlives_crate, ..*providers };
|
||||
}
|
||||
|
||||
fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::ClauseKind<'_>, Span)] {
|
||||
fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clause<'_>, Span)] {
|
||||
let id = tcx.hir().local_def_id_to_hir_id(item_def_id);
|
||||
|
||||
if matches!(tcx.def_kind(item_def_id), hir::def::DefKind::AnonConst)
|
||||
|
@ -52,7 +52,7 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clau
|
|||
if tcx.has_attr(item_def_id, sym::rustc_outlives) {
|
||||
let mut pred: Vec<String> = predicates
|
||||
.iter()
|
||||
.map(|(out_pred, _)| match out_pred {
|
||||
.map(|(out_pred, _)| match out_pred.kind().skip_binder() {
|
||||
ty::ClauseKind::RegionOutlives(p) => p.to_string(),
|
||||
ty::ClauseKind::TypeOutlives(p) => p.to_string(),
|
||||
err => bug!("unexpected clause {:?}", err),
|
||||
|
@ -104,13 +104,15 @@ fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> {
|
|||
|(ty::OutlivesPredicate(kind1, region2), &span)| {
|
||||
match kind1.unpack() {
|
||||
GenericArgKind::Type(ty1) => Some((
|
||||
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty1, *region2)),
|
||||
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty1, *region2))
|
||||
.to_predicate(tcx),
|
||||
span,
|
||||
)),
|
||||
GenericArgKind::Lifetime(region1) => Some((
|
||||
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(
|
||||
region1, *region2,
|
||||
)),
|
||||
))
|
||||
.to_predicate(tcx),
|
||||
span,
|
||||
)),
|
||||
GenericArgKind::Const(_) => {
|
||||
|
|
|
@ -162,28 +162,25 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
|
|||
// which thus mentions `'a` and should thus accept hidden types that borrow 'a
|
||||
// instead of requiring an additional `+ 'a`.
|
||||
match pred.kind().skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
|
||||
ty::ClauseKind::Trait(ty::TraitPredicate {
|
||||
trait_ref: ty::TraitRef { def_id: _, substs, .. },
|
||||
constness: _,
|
||||
polarity: _,
|
||||
})) => {
|
||||
}) => {
|
||||
for subst in &substs[1..] {
|
||||
subst.visit_with(&mut collector);
|
||||
}
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
|
||||
ty::ClauseKind::Projection(ty::ProjectionPredicate {
|
||||
projection_ty: ty::AliasTy { substs, .. },
|
||||
term,
|
||||
})) => {
|
||||
}) => {
|
||||
for subst in &substs[1..] {
|
||||
subst.visit_with(&mut collector);
|
||||
}
|
||||
term.visit_with(&mut collector);
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
|
||||
_,
|
||||
region,
|
||||
))) => {
|
||||
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(_, region)) => {
|
||||
region.visit_with(&mut collector);
|
||||
}
|
||||
_ => {
|
||||
|
|
|
@ -536,33 +536,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
for ty in [first_ty, second_ty] {
|
||||
for (pred, _) in self
|
||||
for (clause, _) in self
|
||||
.tcx
|
||||
.explicit_item_bounds(rpit_def_id)
|
||||
.subst_iter_copied(self.tcx, substs)
|
||||
{
|
||||
let pred = pred.kind().rebind(match pred.kind().skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
|
||||
let pred = clause.kind().rebind(match clause.kind().skip_binder() {
|
||||
ty::ClauseKind::Trait(trait_pred) => {
|
||||
// FIXME(rpitit): This will need to be fixed when we move to associated types
|
||||
assert!(matches!(
|
||||
*trait_pred.trait_ref.self_ty().kind(),
|
||||
ty::Alias(_, ty::AliasTy { def_id, substs: alias_substs, .. })
|
||||
if def_id == rpit_def_id && substs == alias_substs
|
||||
));
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(
|
||||
trait_pred.with_self_ty(self.tcx, ty),
|
||||
))
|
||||
ty::ClauseKind::Trait(trait_pred.with_self_ty(self.tcx, ty))
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(
|
||||
mut proj_pred,
|
||||
)) => {
|
||||
ty::ClauseKind::Projection(mut proj_pred) => {
|
||||
assert!(matches!(
|
||||
*proj_pred.projection_ty.self_ty().kind(),
|
||||
ty::Alias(_, ty::AliasTy { def_id, substs: alias_substs, .. })
|
||||
if def_id == rpit_def_id && substs == alias_substs
|
||||
));
|
||||
proj_pred = proj_pred.with_self_ty(self.tcx, ty);
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj_pred))
|
||||
ty::ClauseKind::Projection(proj_pred)
|
||||
}
|
||||
_ => continue,
|
||||
});
|
||||
|
|
|
@ -92,10 +92,7 @@ pub(super) fn check_fn<'a, 'tcx>(
|
|||
fcx.check_pat_top(¶m.pat, param_ty, ty_span, None);
|
||||
|
||||
// Check that argument is Sized.
|
||||
// The check for a non-trivial pattern is a hack to avoid duplicate warnings
|
||||
// for simple cases like `fn foo(x: Trait)`,
|
||||
// where we would error once on the parameter as a whole, and once on the binding `x`.
|
||||
if param.pat.simple_ident().is_none() && !params_can_be_unsized {
|
||||
if !params_can_be_unsized {
|
||||
fcx.require_type_is_sized(
|
||||
param_ty,
|
||||
param.pat.span,
|
||||
|
|
|
@ -174,7 +174,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self
|
||||
.deduce_closure_signature_from_predicates(
|
||||
expected_ty,
|
||||
self.tcx.explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs),
|
||||
self.tcx
|
||||
.explicit_item_bounds(def_id)
|
||||
.subst_iter_copied(self.tcx, substs)
|
||||
.map(|(c, s)| (c.as_predicate(), s)),
|
||||
),
|
||||
ty::Dynamic(ref object_type, ..) => {
|
||||
let sig = object_type.projection_bounds().find_map(|pb| {
|
||||
|
@ -717,13 +720,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.tcx
|
||||
.explicit_item_bounds(def_id)
|
||||
.subst_iter_copied(self.tcx, substs)
|
||||
.find_map(|(p, s)| get_future_output(p, s))?,
|
||||
.find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
|
||||
ty::Error(_) => return None,
|
||||
ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => self
|
||||
.tcx
|
||||
.explicit_item_bounds(proj.def_id)
|
||||
.subst_iter_copied(self.tcx, proj.substs)
|
||||
.find_map(|(p, s)| get_future_output(p, s))?,
|
||||
.find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
|
||||
_ => span_bug!(
|
||||
self.tcx.def_span(expr_def_id),
|
||||
"async fn generator return type not an inference variable: {ret_ty}"
|
||||
|
|
|
@ -577,7 +577,7 @@ fn check_must_not_suspend_ty<'tcx>(
|
|||
let mut has_emitted = false;
|
||||
for &(predicate, _) in fcx.tcx.explicit_item_bounds(def).skip_binder() {
|
||||
// We only look at the `DefId`, so it is safe to skip the binder here.
|
||||
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ref poly_trait_predicate)) =
|
||||
if let ty::ClauseKind::Trait(ref poly_trait_predicate) =
|
||||
predicate.kind().skip_binder()
|
||||
{
|
||||
let def_id = poly_trait_predicate.trait_ref.def_id;
|
||||
|
|
|
@ -408,9 +408,9 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
predicate
|
||||
.kind()
|
||||
.map_bound(|kind| match kind {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(
|
||||
projection_predicate,
|
||||
)) if projection_predicate.projection_ty.def_id == item_def_id => {
|
||||
ty::ClauseKind::Projection(projection_predicate)
|
||||
if projection_predicate.projection_ty.def_id == item_def_id =>
|
||||
{
|
||||
projection_predicate.term.ty()
|
||||
}
|
||||
_ => None,
|
||||
|
|
|
@ -649,9 +649,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
ct_op: |ct| ct,
|
||||
});
|
||||
|
||||
if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection)) =
|
||||
predicate.kind().skip_binder()
|
||||
{
|
||||
if let ty::ClauseKind::Projection(projection) = predicate.kind().skip_binder() {
|
||||
if projection.term.references_error() {
|
||||
// No point on adding any obligations since there's a type error involved.
|
||||
obligations.clear();
|
||||
|
|
|
@ -296,7 +296,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
|
|||
trace!("{:#?}", bounds.skip_binder());
|
||||
bounds
|
||||
.subst_iter(tcx, alias_ty.substs)
|
||||
.filter_map(|p| p.to_opt_type_outlives())
|
||||
.filter_map(|p| p.as_type_outlives_clause())
|
||||
.filter_map(|p| p.no_bound_vars())
|
||||
.map(|OutlivesPredicate(_, r)| r)
|
||||
}
|
||||
|
|
|
@ -167,13 +167,13 @@ impl<'tcx> Elaboratable<'tcx> for (ty::Predicate<'tcx>, Span) {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Elaboratable<'tcx> for ty::Clause<'tcx> {
|
||||
impl<'tcx> Elaboratable<'tcx> for (ty::Clause<'tcx>, Span) {
|
||||
fn predicate(&self) -> ty::Predicate<'tcx> {
|
||||
self.as_predicate()
|
||||
self.0.as_predicate()
|
||||
}
|
||||
|
||||
fn child(&self, predicate: ty::Predicate<'tcx>) -> Self {
|
||||
predicate.as_clause().unwrap()
|
||||
(predicate.expect_clause(), self.1)
|
||||
}
|
||||
|
||||
fn child_with_derived_cause(
|
||||
|
@ -183,7 +183,27 @@ impl<'tcx> Elaboratable<'tcx> for ty::Clause<'tcx> {
|
|||
_parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
_index: usize,
|
||||
) -> Self {
|
||||
predicate.as_clause().unwrap()
|
||||
(predicate.expect_clause(), self.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Elaboratable<'tcx> for ty::Clause<'tcx> {
|
||||
fn predicate(&self) -> ty::Predicate<'tcx> {
|
||||
self.as_predicate()
|
||||
}
|
||||
|
||||
fn child(&self, predicate: ty::Predicate<'tcx>) -> Self {
|
||||
predicate.expect_clause()
|
||||
}
|
||||
|
||||
fn child_with_derived_cause(
|
||||
&self,
|
||||
predicate: ty::Predicate<'tcx>,
|
||||
_span: Span,
|
||||
_parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
_index: usize,
|
||||
) -> Self {
|
||||
predicate.expect_clause()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1984,12 +1984,12 @@ declare_lint_pass!(ExplicitOutlivesRequirements => [EXPLICIT_OUTLIVES_REQUIREMEN
|
|||
|
||||
impl ExplicitOutlivesRequirements {
|
||||
fn lifetimes_outliving_lifetime<'tcx>(
|
||||
inferred_outlives: &'tcx [(ty::ClauseKind<'tcx>, Span)],
|
||||
inferred_outlives: &'tcx [(ty::Clause<'tcx>, Span)],
|
||||
def_id: DefId,
|
||||
) -> Vec<ty::Region<'tcx>> {
|
||||
inferred_outlives
|
||||
.iter()
|
||||
.filter_map(|(clause, _)| match *clause {
|
||||
.filter_map(|(clause, _)| match clause.kind().skip_binder() {
|
||||
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a {
|
||||
ty::ReEarlyBound(ebr) if ebr.def_id == def_id => Some(b),
|
||||
_ => None,
|
||||
|
@ -2000,12 +2000,12 @@ impl ExplicitOutlivesRequirements {
|
|||
}
|
||||
|
||||
fn lifetimes_outliving_type<'tcx>(
|
||||
inferred_outlives: &'tcx [(ty::ClauseKind<'tcx>, Span)],
|
||||
inferred_outlives: &'tcx [(ty::Clause<'tcx>, Span)],
|
||||
index: u32,
|
||||
) -> Vec<ty::Region<'tcx>> {
|
||||
inferred_outlives
|
||||
.iter()
|
||||
.filter_map(|(clause, _)| match *clause {
|
||||
.filter_map(|(clause, _)| match clause.kind().skip_binder() {
|
||||
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => {
|
||||
a.is_param(index).then_some(b)
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
|
|||
// Liberate bound regions in the predicate since we
|
||||
// don't actually care about lifetimes in this check.
|
||||
let predicate = cx.tcx.liberate_late_bound_regions(def_id, pred.kind());
|
||||
let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) = predicate else {
|
||||
let ty::ClauseKind::Projection(proj) = predicate else {
|
||||
continue;
|
||||
};
|
||||
// Only check types, since those are the only things that may
|
||||
|
@ -133,7 +133,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
|
|||
let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) {
|
||||
(
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }),
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)),
|
||||
ty::ClauseKind::Trait(trait_pred),
|
||||
) => Some(AddBound {
|
||||
suggest_span: cx.tcx.def_span(*def_id).shrink_to_hi(),
|
||||
trait_ref: trait_pred.print_modifiers_and_trait_path(),
|
||||
|
|
|
@ -289,9 +289,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
|||
.filter_only_self()
|
||||
.find_map(|(pred, _span)| {
|
||||
// We only look at the `DefId`, so it is safe to skip the binder here.
|
||||
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(
|
||||
ref poly_trait_predicate,
|
||||
)) = pred.kind().skip_binder()
|
||||
if let ty::ClauseKind::Trait(ref poly_trait_predicate) =
|
||||
pred.kind().skip_binder()
|
||||
{
|
||||
let def_id = poly_trait_predicate.trait_ref.def_id;
|
||||
|
||||
|
|
|
@ -3464,7 +3464,8 @@ declare_lint! {
|
|||
/// out an update in your own time.
|
||||
pub LONG_RUNNING_CONST_EVAL,
|
||||
Deny,
|
||||
"detects long const eval operations"
|
||||
"detects long const eval operations",
|
||||
report_in_external_macro
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
|
|
|
@ -25,7 +25,7 @@ use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
|
|||
use rustc_middle::ty::codec::TyDecoder;
|
||||
use rustc_middle::ty::fast_reject::SimplifiedType;
|
||||
use rustc_middle::ty::GeneratorDiagnosticData;
|
||||
use rustc_middle::ty::{self, ParameterizedOverTcx, Predicate, Ty, TyCtxt, Visibility};
|
||||
use rustc_middle::ty::{self, ParameterizedOverTcx, Ty, TyCtxt, Visibility};
|
||||
use rustc_serialize::opaque::MemDecoder;
|
||||
use rustc_serialize::{Decodable, Decoder};
|
||||
use rustc_session::cstore::{
|
||||
|
@ -642,6 +642,12 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [(ty::Clause<'tcx>, Span)] {
|
||||
fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self {
|
||||
ty::codec::RefDecodable::decode(d)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyValue<T> {
|
||||
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self {
|
||||
decoder.read_lazy()
|
||||
|
@ -854,7 +860,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
|||
self,
|
||||
index: DefIndex,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> ty::EarlyBinder<&'tcx [(Predicate<'tcx>, Span)]> {
|
||||
) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> {
|
||||
let lazy = self.root.tables.explicit_item_bounds.get(self, index);
|
||||
let output = if lazy.is_default() {
|
||||
&mut []
|
||||
|
|
|
@ -375,8 +375,8 @@ define_tables! {
|
|||
is_type_alias_impl_trait: Table<DefIndex, bool>,
|
||||
attr_flags: Table<DefIndex, AttrFlags>,
|
||||
def_path_hashes: Table<DefIndex, DefPathHash>,
|
||||
explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Predicate<'static>, Span)>>,
|
||||
inferred_outlives_of: Table<DefIndex, LazyArray<(ty::ClauseKind<'static>, Span)>>,
|
||||
explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
|
||||
inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
|
||||
inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
|
||||
associated_types_for_impl_traits_in_associated_fn: Table<DefIndex, LazyArray<DefId>>,
|
||||
opt_rpitit_info: Table<DefIndex, Option<LazyValue<ty::ImplTraitInTraitData>>>,
|
||||
|
|
|
@ -346,7 +346,7 @@ rustc_queries! {
|
|||
/// `key` is the `DefId` of the associated type or opaque type.
|
||||
///
|
||||
/// Bounds from the parent (e.g. with nested impl trait) are not included.
|
||||
query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx [(ty::Predicate<'tcx>, Span)]> {
|
||||
query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> {
|
||||
desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
|
||||
cache_on_disk_if { key.is_local() }
|
||||
separate_provide_extern
|
||||
|
@ -373,7 +373,7 @@ rustc_queries! {
|
|||
/// ```
|
||||
///
|
||||
/// Bounds from the parent (e.g. with nested impl trait) are not included.
|
||||
query item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx ty::List<ty::Predicate<'tcx>>> {
|
||||
query item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx ty::List<ty::Clause<'tcx>>> {
|
||||
desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) }
|
||||
}
|
||||
|
||||
|
@ -647,7 +647,7 @@ rustc_queries! {
|
|||
|
||||
/// Returns the inferred outlives predicates (e.g., for `struct
|
||||
/// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`).
|
||||
query inferred_outlives_of(key: DefId) -> &'tcx [(ty::ClauseKind<'tcx>, Span)] {
|
||||
query inferred_outlives_of(key: DefId) -> &'tcx [(ty::Clause<'tcx>, Span)] {
|
||||
desc { |tcx| "computing inferred outlives predicates of `{}`", tcx.def_path_str(key) }
|
||||
cache_on_disk_if { key.is_local() }
|
||||
separate_provide_extern
|
||||
|
|
|
@ -798,7 +798,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::ClauseKind<'tcx>, Span)] {
|
||||
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Clause<'tcx>, Span)] {
|
||||
#[inline]
|
||||
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
|
||||
RefDecodable::decode(d)
|
||||
|
|
|
@ -128,6 +128,12 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Predicate<'tcx>
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Clause<'tcx> {
|
||||
fn encode(&self, e: &mut E) {
|
||||
self.as_predicate().encode(e);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Region<'tcx> {
|
||||
fn encode(&self, e: &mut E) {
|
||||
self.kind().encode(e);
|
||||
|
@ -241,6 +247,13 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Predicate<'tcx>
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Clause<'tcx> {
|
||||
fn decode(decoder: &mut D) -> ty::Clause<'tcx> {
|
||||
let pred: ty::Predicate<'tcx> = Decodable::decode(decoder);
|
||||
pred.expect_clause()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for SubstsRef<'tcx> {
|
||||
fn decode(decoder: &mut D) -> Self {
|
||||
let len = decoder.read_usize();
|
||||
|
@ -365,9 +378,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
|
||||
for [(ty::ClauseKind<'tcx>, Span)]
|
||||
{
|
||||
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [(ty::Clause<'tcx>, Span)] {
|
||||
fn decode(decoder: &mut D) -> &'tcx Self {
|
||||
decoder.interner().arena.alloc_from_iter(
|
||||
(0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::<Vec<_>>(),
|
||||
|
|
|
@ -25,10 +25,10 @@ use crate::traits::solve::{
|
|||
ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, PredefinedOpaquesData,
|
||||
};
|
||||
use crate::ty::{
|
||||
self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, FloatTy, FloatVar, FloatVid,
|
||||
GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
|
||||
PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind, ReprOptions,
|
||||
TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, Visibility,
|
||||
self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Const, ConstData, FloatTy, FloatVar,
|
||||
FloatVid, GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst,
|
||||
ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind,
|
||||
ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, Visibility,
|
||||
};
|
||||
use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
|
||||
use rustc_ast::{self as ast, attr};
|
||||
|
@ -141,7 +141,9 @@ pub struct CtxtInterners<'tcx> {
|
|||
region: InternedSet<'tcx, RegionKind<'tcx>>,
|
||||
poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>,
|
||||
predicate: InternedSet<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
|
||||
// FIXME(clause): remove this when all usages are moved to predicate
|
||||
predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
|
||||
clauses: InternedSet<'tcx, List<Clause<'tcx>>>,
|
||||
projs: InternedSet<'tcx, List<ProjectionKind>>,
|
||||
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
|
||||
const_: InternedSet<'tcx, ConstData<'tcx>>,
|
||||
|
@ -167,6 +169,7 @@ impl<'tcx> CtxtInterners<'tcx> {
|
|||
canonical_var_infos: Default::default(),
|
||||
predicate: Default::default(),
|
||||
predicates: Default::default(),
|
||||
clauses: Default::default(),
|
||||
projs: Default::default(),
|
||||
place_elems: Default::default(),
|
||||
const_: Default::default(),
|
||||
|
@ -1533,6 +1536,7 @@ slice_interners!(
|
|||
canonical_var_infos: pub mk_canonical_var_infos(CanonicalVarInfo<'tcx>),
|
||||
poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>),
|
||||
predicates: intern_predicates(Predicate<'tcx>),
|
||||
clauses: intern_clauses(Clause<'tcx>),
|
||||
projs: pub mk_projs(ProjectionKind),
|
||||
place_elems: pub mk_place_elems(PlaceElem<'tcx>),
|
||||
bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind),
|
||||
|
@ -1564,7 +1568,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
let future_trait = self.require_lang_item(LangItem::Future, None);
|
||||
|
||||
self.explicit_item_bounds(def_id).skip_binder().iter().any(|&(predicate, _)| {
|
||||
let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder() else {
|
||||
let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() else {
|
||||
return false;
|
||||
};
|
||||
trait_predicate.trait_ref.def_id == future_trait
|
||||
|
@ -2084,6 +2088,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self.intern_predicates(preds)
|
||||
}
|
||||
|
||||
pub fn mk_clauses(self, preds: &[Clause<'tcx>]) -> &'tcx List<Clause<'tcx>> {
|
||||
// FIXME consider asking the input slice to be sorted to avoid
|
||||
// re-interning permutations, in which case that would be asserted
|
||||
// here.
|
||||
self.intern_clauses(preds)
|
||||
}
|
||||
|
||||
pub fn mk_const_list_from_iter<I, T>(self, iter: I) -> T::Output
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
|
@ -2135,6 +2146,14 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
T::collect_and_apply(iter, |xs| self.mk_predicates(xs))
|
||||
}
|
||||
|
||||
pub fn mk_clauses_from_iter<I, T>(self, iter: I) -> T::Output
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
T: CollectAndApply<Clause<'tcx>, &'tcx List<Clause<'tcx>>>,
|
||||
{
|
||||
T::collect_and_apply(iter, |xs| self.mk_clauses(xs))
|
||||
}
|
||||
|
||||
pub fn mk_type_list_from_iter<I, T>(self, iter: I) -> T::Output
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
|
|
|
@ -318,7 +318,13 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
|||
Ok(layout) => {
|
||||
return Ok(SizeSkeleton::Known(layout.size));
|
||||
}
|
||||
Err(err) => err,
|
||||
Err(err @ LayoutError::Unknown(_)) => err,
|
||||
// We can't extract SizeSkeleton info from other layout errors
|
||||
Err(
|
||||
e @ LayoutError::Cycle
|
||||
| e @ LayoutError::SizeOverflow(_)
|
||||
| e @ LayoutError::NormalizationFailure(..),
|
||||
) => return Err(e),
|
||||
};
|
||||
|
||||
match *ty.kind() {
|
||||
|
|
|
@ -602,6 +602,24 @@ impl<'tcx> Clause<'tcx> {
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_type_outlives_clause(self) -> Option<Binder<'tcx, TypeOutlivesPredicate<'tcx>>> {
|
||||
let clause = self.kind();
|
||||
if let ty::ClauseKind::TypeOutlives(o) = clause.skip_binder() {
|
||||
Some(clause.rebind(o))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_region_outlives_clause(self) -> Option<Binder<'tcx, RegionOutlivesPredicate<'tcx>>> {
|
||||
let clause = self.kind();
|
||||
if let ty::ClauseKind::RegionOutlives(o) = clause.skip_binder() {
|
||||
Some(clause.rebind(o))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
|
||||
|
@ -713,7 +731,7 @@ pub struct CratePredicatesMap<'tcx> {
|
|||
/// predicate of its outlive bounds. If an item has no outlives
|
||||
/// bounds, it will have no entry.
|
||||
// FIXME(clause): should this be a `Clause`?
|
||||
pub predicates: FxHashMap<DefId, &'tcx [(ClauseKind<'tcx>, Span)]>,
|
||||
pub predicates: FxHashMap<DefId, &'tcx [(Clause<'tcx>, Span)]>,
|
||||
}
|
||||
|
||||
impl<'tcx> Predicate<'tcx> {
|
||||
|
@ -1243,7 +1261,21 @@ impl<'tcx> ToPredicate<'tcx> for ClauseKind<'tcx> {
|
|||
impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, ClauseKind<'tcx>> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
tcx.mk_predicate(self.map_bound(|clause| ty::PredicateKind::Clause(clause)))
|
||||
tcx.mk_predicate(self.map_bound(ty::PredicateKind::Clause))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
self.as_predicate()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ClauseKind<'tcx> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
|
||||
tcx.mk_predicate(Binder::dummy(ty::PredicateKind::Clause(self))).expect_clause()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -128,6 +128,7 @@ parameterized_over_tcx! {
|
|||
ty::TraitRef,
|
||||
ty::Const,
|
||||
ty::Predicate,
|
||||
ty::Clause,
|
||||
ty::ClauseKind,
|
||||
ty::GeneratorDiagnosticData,
|
||||
}
|
||||
|
|
|
@ -928,7 +928,7 @@ pub trait PrettyPrinter<'tcx>:
|
|||
let bound_predicate = predicate.kind();
|
||||
|
||||
match bound_predicate.skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
|
||||
ty::ClauseKind::Trait(pred) => {
|
||||
let trait_ref = bound_predicate.rebind(pred.trait_ref);
|
||||
|
||||
// Don't print + Sized, but rather + ?Sized if absent.
|
||||
|
@ -939,7 +939,7 @@ pub trait PrettyPrinter<'tcx>:
|
|||
|
||||
self.insert_trait_and_projection(trait_ref, None, &mut traits, &mut fn_traits);
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
|
||||
ty::ClauseKind::Projection(pred) => {
|
||||
let proj_ref = bound_predicate.rebind(pred);
|
||||
let trait_ref = proj_ref.required_poly_trait_ref(tcx);
|
||||
|
||||
|
@ -953,7 +953,7 @@ pub trait PrettyPrinter<'tcx>:
|
|||
&mut fn_traits,
|
||||
);
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(outlives)) => {
|
||||
ty::ClauseKind::TypeOutlives(outlives) => {
|
||||
lifetimes.push(outlives.1);
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
@ -666,10 +666,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Clause<'tcx> {
|
|||
self,
|
||||
folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
Ok(folder
|
||||
.try_fold_predicate(self.as_predicate())?
|
||||
.as_clause()
|
||||
.expect("no sensible folder would do this"))
|
||||
Ok(folder.try_fold_predicate(self.as_predicate())?.expect_clause())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -713,6 +710,15 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Predicate<'tcx>> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Clause<'tcx>> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
ty::util::fold_list(self, folder, |tcx, v| tcx.mk_clauses(v))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
|
|
|
@ -1824,7 +1824,7 @@ fn check_must_not_suspend_ty<'tcx>(
|
|||
let mut has_emitted = false;
|
||||
for &(predicate, _) in tcx.explicit_item_bounds(def).skip_binder() {
|
||||
// We only look at the `DefId`, so it is safe to skip the binder here.
|
||||
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ref poly_trait_predicate)) =
|
||||
if let ty::ClauseKind::Trait(ref poly_trait_predicate) =
|
||||
predicate.kind().skip_binder()
|
||||
{
|
||||
let def_id = poly_trait_predicate.trait_ref.def_id;
|
||||
|
|
|
@ -114,6 +114,12 @@ trait DefIdVisitor<'tcx> {
|
|||
) -> ControlFlow<Self::BreakTy> {
|
||||
self.skeleton().visit_predicates(predicates)
|
||||
}
|
||||
fn visit_clauses(
|
||||
&mut self,
|
||||
predicates: &[(ty::Clause<'tcx>, Span)],
|
||||
) -> ControlFlow<Self::BreakTy> {
|
||||
self.skeleton().visit_clauses(predicates)
|
||||
}
|
||||
}
|
||||
|
||||
struct DefIdVisitorSkeleton<'v, 'tcx, V: ?Sized> {
|
||||
|
@ -159,42 +165,23 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<V::BreakTy> {
|
||||
match predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
|
||||
trait_ref,
|
||||
constness: _,
|
||||
polarity: _,
|
||||
})) => self.visit_trait(trait_ref),
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
|
||||
projection_ty,
|
||||
term,
|
||||
})) => {
|
||||
fn visit_clause(&mut self, clause: ty::Clause<'tcx>) -> ControlFlow<V::BreakTy> {
|
||||
match clause.kind().skip_binder() {
|
||||
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, constness: _, polarity: _ }) => {
|
||||
self.visit_trait(trait_ref)
|
||||
}
|
||||
ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => {
|
||||
term.visit_with(self)?;
|
||||
self.visit_projection_ty(projection_ty)
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
|
||||
ty,
|
||||
_region,
|
||||
))) => ty.visit_with(self),
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) => {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
|
||||
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => ty.visit_with(self),
|
||||
ty::ClauseKind::RegionOutlives(..) => ControlFlow::Continue(()),
|
||||
ty::ClauseKind::ConstArgHasType(ct, ty) => {
|
||||
ct.visit_with(self)?;
|
||||
ty.visit_with(self)
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => ct.visit_with(self),
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => arg.visit_with(self),
|
||||
|
||||
ty::PredicateKind::ObjectSafe(_)
|
||||
| ty::PredicateKind::ClosureKind(_, _, _)
|
||||
| ty::PredicateKind::Subtype(_)
|
||||
| ty::PredicateKind::Coerce(_)
|
||||
| ty::PredicateKind::ConstEquate(_, _)
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(_)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
| ty::PredicateKind::AliasRelate(..) => bug!("unexpected predicate: {:?}", predicate),
|
||||
ty::ClauseKind::ConstEvaluatable(ct) => ct.visit_with(self),
|
||||
ty::ClauseKind::WellFormed(arg) => arg.visit_with(self),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,7 +190,16 @@ where
|
|||
predicates: ty::GenericPredicates<'tcx>,
|
||||
) -> ControlFlow<V::BreakTy> {
|
||||
let ty::GenericPredicates { parent: _, predicates } = predicates;
|
||||
predicates.iter().try_for_each(|&(predicate, _span)| self.visit_predicate(predicate))
|
||||
predicates.iter().try_for_each(|&(predicate, _span)| {
|
||||
let clause = predicate
|
||||
.as_clause()
|
||||
.unwrap_or_else(|| bug!("unexpected predicate: {:?}", predicate));
|
||||
self.visit_clause(clause)
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> ControlFlow<V::BreakTy> {
|
||||
clauses.iter().try_for_each(|&(clause, _span)| self.visit_clause(clause))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,10 +303,7 @@ where
|
|||
// through the trait list (default type visitor doesn't visit those traits).
|
||||
// All traits in the list are considered the "primary" part of the type
|
||||
// and are visited by shallow visitors.
|
||||
self.visit_predicates(ty::GenericPredicates {
|
||||
parent: None,
|
||||
predicates: tcx.explicit_item_bounds(def_id).skip_binder(),
|
||||
})?;
|
||||
self.visit_clauses(tcx.explicit_item_bounds(def_id).skip_binder())?;
|
||||
}
|
||||
}
|
||||
// These types don't have their own def-ids (but may have subcomponents
|
||||
|
@ -1814,10 +1807,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
|
|||
|
||||
fn bounds(&mut self) -> &mut Self {
|
||||
self.in_primary_interface = false;
|
||||
self.visit_predicates(ty::GenericPredicates {
|
||||
parent: None,
|
||||
predicates: self.tcx.explicit_item_bounds(self.item_def_id).skip_binder(),
|
||||
});
|
||||
self.visit_clauses(self.tcx.explicit_item_bounds(self.item_def_id).skip_binder());
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
@ -522,13 +522,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
|
||||
for assumption in self.tcx().item_bounds(alias_ty.def_id).subst(self.tcx(), alias_ty.substs)
|
||||
{
|
||||
if let Some(clause) = assumption.as_clause() {
|
||||
match G::consider_alias_bound_candidate(self, goal, clause) {
|
||||
Ok(result) => {
|
||||
candidates.push(Candidate { source: CandidateSource::AliasBound, result })
|
||||
}
|
||||
Err(NoSolution) => (),
|
||||
match G::consider_alias_bound_candidate(self, goal, assumption) {
|
||||
Ok(result) => {
|
||||
candidates.push(Candidate { source: CandidateSource::AliasBound, result })
|
||||
}
|
||||
Err(NoSolution) => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -353,7 +353,11 @@ pub(in crate::solve) fn predicates_for_object_candidate<'tcx>(
|
|||
// FIXME(associated_const_equality): Also add associated consts to
|
||||
// the requirements here.
|
||||
if item.kind == ty::AssocKind::Type {
|
||||
requirements.extend(tcx.item_bounds(item.def_id).subst(tcx, trait_ref.substs));
|
||||
requirements.extend(
|
||||
tcx.item_bounds(item.def_id)
|
||||
.subst_iter(tcx, trait_ref.substs)
|
||||
.map(|clause| clause.as_predicate()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1157,7 +1157,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
|
||||
self.tcx.item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| {
|
||||
if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) = pred.kind().skip_binder()
|
||||
if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
|
||||
&& Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
|
||||
// args tuple will always be substs[1]
|
||||
&& let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
|
||||
|
|
|
@ -271,7 +271,7 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span
|
|||
.in_definition_order()
|
||||
.filter(|item| item.kind == ty::AssocKind::Type)
|
||||
.flat_map(|item| tcx.explicit_item_bounds(item.def_id).subst_identity_iter_copied())
|
||||
.filter_map(|pred_span| predicate_references_self(tcx, pred_span))
|
||||
.filter_map(|(clause, span)| predicate_references_self(tcx, (clause.as_predicate(), span)))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
|
|
@ -1585,7 +1585,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
|
|||
obligation,
|
||||
candidate_set,
|
||||
ProjectionCandidate::TraitDef,
|
||||
bounds.iter(),
|
||||
bounds.iter().map(|clause| clause.as_predicate()),
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -170,7 +170,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
let candidate_predicate = tcx.item_bounds(def_id).map_bound(|i| i[idx]).subst(tcx, substs);
|
||||
let candidate = candidate_predicate
|
||||
.to_opt_poly_trait_pred()
|
||||
.as_trait_clause()
|
||||
.expect("projection candidate is not a trait predicate")
|
||||
.map_bound(|t| t.trait_ref);
|
||||
let mut obligations = Vec::new();
|
||||
|
@ -631,7 +631,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
let assoc_ty_substs = tcx.mk_substs(&substs);
|
||||
let bound =
|
||||
bound.map_bound(|b| b.kind().skip_binder()).subst(tcx, assoc_ty_substs);
|
||||
tcx.mk_predicate(ty::Binder::bind_with_vars(bound, bound_vars))
|
||||
ty::Binder::bind_with_vars(bound, bound_vars).to_predicate(tcx)
|
||||
};
|
||||
let normalized_bound = normalize_with_depth_to(
|
||||
self,
|
||||
|
|
|
@ -1668,9 +1668,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
.enumerate()
|
||||
.filter_map(|(idx, bound)| {
|
||||
let bound_predicate = bound.kind();
|
||||
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
|
||||
bound_predicate.skip_binder()
|
||||
{
|
||||
if let ty::ClauseKind::Trait(pred) = bound_predicate.skip_binder() {
|
||||
let bound = bound_predicate.rebind(pred.trait_ref);
|
||||
if self.infcx.probe(|_| {
|
||||
match self.match_normalize_trait_ref(
|
||||
|
|
|
@ -54,7 +54,9 @@ impl<'tcx> RustIrDatabase<'tcx> {
|
|||
.tcx
|
||||
.explicit_item_bounds(def_id)
|
||||
.subst_iter_copied(self.interner.tcx, &bound_vars)
|
||||
.filter_map(|(bound, _)| LowerInto::<Option<_>>::lower_into(bound, self.interner))
|
||||
.filter_map(|(bound, _)| {
|
||||
LowerInto::<Option<_>>::lower_into(bound.as_predicate(), self.interner)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
@ -520,7 +522,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
|
|||
.filter_map(|bound| {
|
||||
LowerInto::<
|
||||
Option<chalk_ir::QuantifiedWhereClause<RustInterner<'tcx>>>
|
||||
>::lower_into(bound, self.interner)
|
||||
>::lower_into(bound.as_predicate(), self.interner)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
|
@ -145,17 +145,35 @@ fn layout_of_uncached<'tcx>(
|
|||
return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr)));
|
||||
}
|
||||
|
||||
let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
|
||||
|
||||
let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type()
|
||||
// Projection eagerly bails out when the pointee references errors,
|
||||
// fall back to structurally deducing metadata.
|
||||
&& !pointee.references_error()
|
||||
{
|
||||
let metadata_ty = tcx.normalize_erasing_regions(
|
||||
let pointee_metadata = tcx.mk_projection(metadata_def_id, [pointee]);
|
||||
let metadata_ty = match tcx.try_normalize_erasing_regions(
|
||||
param_env,
|
||||
tcx.mk_projection(metadata_def_id, [pointee]),
|
||||
);
|
||||
pointee_metadata,
|
||||
) {
|
||||
Ok(metadata_ty) => metadata_ty,
|
||||
Err(mut err) => {
|
||||
// Usually `<Ty as Pointee>::Metadata` can't be normalized because
|
||||
// its struct tail cannot be normalized either, so try to get a
|
||||
// more descriptive layout error here, which will lead to less confusing
|
||||
// diagnostics.
|
||||
match tcx.try_normalize_erasing_regions(
|
||||
param_env,
|
||||
tcx.struct_tail_without_normalization(pointee),
|
||||
) {
|
||||
Ok(_) => {},
|
||||
Err(better_err) => {
|
||||
err = better_err;
|
||||
}
|
||||
}
|
||||
return Err(LayoutError::NormalizationFailure(pointee, err));
|
||||
},
|
||||
};
|
||||
|
||||
let metadata_layout = cx.layout_of(metadata_ty)?;
|
||||
// If the metadata is a 1-zst, then the pointer is thin.
|
||||
if metadata_layout.is_zst() && metadata_layout.align.abi.bytes() == 1 {
|
||||
|
@ -163,10 +181,13 @@ fn layout_of_uncached<'tcx>(
|
|||
}
|
||||
|
||||
let Abi::Scalar(metadata) = metadata_layout.abi else {
|
||||
return Err(LayoutError::Unknown(unsized_part));
|
||||
return Err(LayoutError::Unknown(pointee));
|
||||
};
|
||||
|
||||
metadata
|
||||
} else {
|
||||
let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
|
||||
|
||||
match unsized_part.kind() {
|
||||
ty::Foreign(..) => {
|
||||
return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr)));
|
||||
|
@ -178,7 +199,7 @@ fn layout_of_uncached<'tcx>(
|
|||
vtable
|
||||
}
|
||||
_ => {
|
||||
return Err(LayoutError::Unknown(unsized_part));
|
||||
return Err(LayoutError::Unknown(pointee));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -54,9 +54,9 @@ impl Config {
|
|||
/// Runs a command, printing out nice contextual information if it fails.
|
||||
/// Exits if the command failed to execute at all, otherwise returns its
|
||||
/// `status.success()`.
|
||||
pub(crate) fn try_run(&self, cmd: &mut Command) -> bool {
|
||||
pub(crate) fn try_run(&self, cmd: &mut Command) -> Result<(), ()> {
|
||||
if self.dry_run() {
|
||||
return true;
|
||||
return Ok(());
|
||||
}
|
||||
self.verbose(&format!("running: {:?}", cmd));
|
||||
try_run(cmd, self.is_verbose())
|
||||
|
@ -156,12 +156,14 @@ impl Config {
|
|||
];
|
||||
}
|
||||
";
|
||||
nix_build_succeeded = self.try_run(Command::new("nix-build").args(&[
|
||||
Path::new("-E"),
|
||||
Path::new(NIX_EXPR),
|
||||
Path::new("-o"),
|
||||
&nix_deps_dir,
|
||||
]));
|
||||
nix_build_succeeded = self
|
||||
.try_run(Command::new("nix-build").args(&[
|
||||
Path::new("-E"),
|
||||
Path::new(NIX_EXPR),
|
||||
Path::new("-o"),
|
||||
&nix_deps_dir,
|
||||
]))
|
||||
.is_ok();
|
||||
nix_deps_dir
|
||||
});
|
||||
if !nix_build_succeeded {
|
||||
|
@ -186,7 +188,7 @@ impl Config {
|
|||
patchelf.args(&["--set-interpreter", dynamic_linker.trim_end()]);
|
||||
}
|
||||
|
||||
self.try_run(patchelf.arg(fname));
|
||||
self.try_run(patchelf.arg(fname)).unwrap();
|
||||
}
|
||||
|
||||
fn download_file(&self, url: &str, dest_path: &Path, help_on_error: &str) {
|
||||
|
@ -237,7 +239,7 @@ impl Config {
|
|||
"(New-Object System.Net.WebClient).DownloadFile('{}', '{}')",
|
||||
url, tempfile.to_str().expect("invalid UTF-8 not supported with powershell downloads"),
|
||||
),
|
||||
])) {
|
||||
])).is_err() {
|
||||
return;
|
||||
}
|
||||
eprintln!("\nspurious failure, trying again");
|
||||
|
|
|
@ -333,7 +333,7 @@ forward! {
|
|||
create(path: &Path, s: &str),
|
||||
remove(f: &Path),
|
||||
tempdir() -> PathBuf,
|
||||
try_run(cmd: &mut Command) -> bool,
|
||||
try_run(cmd: &mut Command) -> Result<(), ()>,
|
||||
llvm_link_shared() -> bool,
|
||||
download_rustc() -> bool,
|
||||
initial_rustfmt() -> Option<PathBuf>,
|
||||
|
@ -614,11 +614,13 @@ impl Build {
|
|||
}
|
||||
|
||||
// Save any local changes, but avoid running `git stash pop` if there are none (since it will exit with an error).
|
||||
let has_local_modifications = !self.try_run(
|
||||
Command::new("git")
|
||||
.args(&["diff-index", "--quiet", "HEAD"])
|
||||
.current_dir(&absolute_path),
|
||||
);
|
||||
let has_local_modifications = self
|
||||
.try_run(
|
||||
Command::new("git")
|
||||
.args(&["diff-index", "--quiet", "HEAD"])
|
||||
.current_dir(&absolute_path),
|
||||
)
|
||||
.is_err();
|
||||
if has_local_modifications {
|
||||
self.run(Command::new("git").args(&["stash", "push"]).current_dir(&absolute_path));
|
||||
}
|
||||
|
|
|
@ -27,7 +27,8 @@ impl Step for ExpandYamlAnchors {
|
|||
try_run(
|
||||
builder,
|
||||
&mut builder.tool_cmd(Tool::ExpandYamlAnchors).arg("generate").arg(&builder.src),
|
||||
);
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
|
@ -39,17 +40,17 @@ impl Step for ExpandYamlAnchors {
|
|||
}
|
||||
}
|
||||
|
||||
fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> bool {
|
||||
fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> Result<(), ()> {
|
||||
if !builder.fail_fast {
|
||||
if !builder.try_run(cmd) {
|
||||
if let Err(e) = builder.try_run(cmd) {
|
||||
let mut failures = builder.delayed_failures.borrow_mut();
|
||||
failures.push(format!("{:?}", cmd));
|
||||
return false;
|
||||
return Err(e);
|
||||
}
|
||||
} else {
|
||||
builder.run(cmd);
|
||||
}
|
||||
true
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
|
|
|
@ -48,17 +48,17 @@ const MIR_OPT_BLESS_TARGET_MAPPING: &[(&str, &str)] = &[
|
|||
// build for, so there is no entry for "aarch64-apple-darwin" here.
|
||||
];
|
||||
|
||||
fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> bool {
|
||||
fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> Result<(), ()> {
|
||||
if !builder.fail_fast {
|
||||
if !builder.try_run(cmd) {
|
||||
if let Err(e) = builder.try_run(cmd) {
|
||||
let mut failures = builder.delayed_failures.borrow_mut();
|
||||
failures.push(format!("{:?}", cmd));
|
||||
return false;
|
||||
return Err(e);
|
||||
}
|
||||
} else {
|
||||
builder.run(cmd);
|
||||
}
|
||||
true
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn try_run_quiet(builder: &Builder<'_>, cmd: &mut Command) -> bool {
|
||||
|
@ -187,7 +187,8 @@ You can skip linkcheck with --exclude src/tools/linkchecker"
|
|||
try_run(
|
||||
builder,
|
||||
builder.tool_cmd(Tool::Linkchecker).arg(builder.out.join(host.triple).join("doc")),
|
||||
);
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
|
@ -240,7 +241,8 @@ impl Step for HtmlCheck {
|
|||
builder.default_doc(&[]);
|
||||
builder.ensure(crate::doc::Rustc::new(builder.top_stage, self.target, builder));
|
||||
|
||||
try_run(builder, builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target)));
|
||||
try_run(builder, builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target)))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -286,7 +288,8 @@ impl Step for Cargotest {
|
|||
.args(builder.config.test_args())
|
||||
.env("RUSTC", builder.rustc(compiler))
|
||||
.env("RUSTDOC", builder.rustdoc(compiler)),
|
||||
);
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -785,7 +788,7 @@ impl Step for Clippy {
|
|||
cargo.add_rustc_lib_path(builder, compiler);
|
||||
let mut cargo = prepare_cargo_test(cargo, &[], &[], "clippy", compiler, host, builder);
|
||||
|
||||
if builder.try_run(&mut cargo) {
|
||||
if builder.try_run(&mut cargo).is_ok() {
|
||||
// The tests succeeded; nothing to do.
|
||||
return;
|
||||
}
|
||||
|
@ -858,7 +861,7 @@ impl Step for RustdocTheme {
|
|||
util::lld_flag_no_threads(self.compiler.host.contains("windows")),
|
||||
);
|
||||
}
|
||||
try_run(builder, &mut cmd);
|
||||
try_run(builder, &mut cmd).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1109,7 +1112,7 @@ help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy`
|
|||
}
|
||||
|
||||
builder.info("tidy check");
|
||||
try_run(builder, &mut cmd);
|
||||
try_run(builder, &mut cmd).unwrap();
|
||||
|
||||
builder.ensure(ExpandYamlAnchors);
|
||||
|
||||
|
@ -1157,7 +1160,8 @@ impl Step for ExpandYamlAnchors {
|
|||
try_run(
|
||||
builder,
|
||||
&mut builder.tool_cmd(Tool::ExpandYamlAnchors).arg("check").arg(&builder.src),
|
||||
);
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
|
@ -1936,7 +1940,7 @@ impl BookTest {
|
|||
compiler.host,
|
||||
);
|
||||
let _time = util::timeit(&builder);
|
||||
let toolstate = if try_run(builder, &mut rustbook_cmd) {
|
||||
let toolstate = if try_run(builder, &mut rustbook_cmd).is_ok() {
|
||||
ToolState::TestPass
|
||||
} else {
|
||||
ToolState::TestFail
|
||||
|
@ -2094,7 +2098,7 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) ->
|
|||
cmd.arg("--test-args").arg(test_args);
|
||||
|
||||
if builder.config.verbose_tests {
|
||||
try_run(builder, &mut cmd)
|
||||
try_run(builder, &mut cmd).is_ok()
|
||||
} else {
|
||||
try_run_quiet(builder, &mut cmd)
|
||||
}
|
||||
|
@ -2122,7 +2126,7 @@ impl Step for RustcGuide {
|
|||
|
||||
let src = builder.src.join(relative_path);
|
||||
let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
|
||||
let toolstate = if try_run(builder, rustbook_cmd.arg("linkcheck").arg(&src)) {
|
||||
let toolstate = if try_run(builder, rustbook_cmd.arg("linkcheck").arg(&src)).is_ok() {
|
||||
ToolState::TestPass
|
||||
} else {
|
||||
ToolState::TestFail
|
||||
|
@ -2661,7 +2665,7 @@ impl Step for Bootstrap {
|
|||
fn run(self, builder: &Builder<'_>) {
|
||||
let mut check_bootstrap = Command::new(&builder.python());
|
||||
check_bootstrap.arg("bootstrap_test.py").current_dir(builder.src.join("src/bootstrap/"));
|
||||
try_run(builder, &mut check_bootstrap);
|
||||
try_run(builder, &mut check_bootstrap).unwrap();
|
||||
|
||||
let host = builder.config.build;
|
||||
let compiler = builder.compiler(0, host);
|
||||
|
@ -2733,7 +2737,7 @@ impl Step for TierCheck {
|
|||
}
|
||||
|
||||
builder.info("platform support check");
|
||||
try_run(builder, &mut cargo.into());
|
||||
try_run(builder, &mut cargo.into()).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2813,7 +2817,7 @@ impl Step for RustInstaller {
|
|||
cmd.env("CARGO", &builder.initial_cargo);
|
||||
cmd.env("RUSTC", &builder.initial_rustc);
|
||||
cmd.env("TMP_DIR", &tmpdir);
|
||||
try_run(builder, &mut cmd);
|
||||
try_run(builder, &mut cmd).unwrap();
|
||||
}
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
|
|
|
@ -107,7 +107,7 @@ impl Step for ToolBuild {
|
|||
);
|
||||
|
||||
let mut cargo = Command::from(cargo);
|
||||
let is_expected = builder.try_run(&mut cargo);
|
||||
let is_expected = builder.try_run(&mut cargo).is_ok();
|
||||
|
||||
builder.save_toolstate(
|
||||
tool,
|
||||
|
|
|
@ -228,7 +228,7 @@ pub fn is_valid_test_suite_arg<'a, P: AsRef<Path>>(
|
|||
}
|
||||
|
||||
pub fn run(cmd: &mut Command, print_cmd_on_fail: bool) {
|
||||
if !try_run(cmd, print_cmd_on_fail) {
|
||||
if try_run(cmd, print_cmd_on_fail).is_err() {
|
||||
crate::detail_exit_macro!(1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,6 +110,9 @@ There are a number of supported commands:
|
|||
|
||||
* `@has-dir PATH` checks for the existence of the given directory.
|
||||
|
||||
* `@files FOLDER_PATH [ENTRIES]`, checks that `FOLDER_PATH` contains exactly
|
||||
`[ENTRIES]`.
|
||||
|
||||
All conditions can be negated with `!`. `@!has foo/type.NoSuch.html`
|
||||
checks if the given file does not exist, for example.
|
||||
|
||||
|
@ -321,12 +324,15 @@ class CachedFiles(object):
|
|||
else:
|
||||
return self.last_path
|
||||
|
||||
def get_absolute_path(self, path):
|
||||
return os.path.join(self.root, path)
|
||||
|
||||
def get_file(self, path):
|
||||
path = self.resolve_path(path)
|
||||
if path in self.files:
|
||||
return self.files[path]
|
||||
|
||||
abspath = os.path.join(self.root, path)
|
||||
abspath = self.get_absolute_path(path)
|
||||
if not(os.path.exists(abspath) and os.path.isfile(abspath)):
|
||||
raise FailedCheck('File does not exist {!r}'.format(path))
|
||||
|
||||
|
@ -340,7 +346,7 @@ class CachedFiles(object):
|
|||
if path in self.trees:
|
||||
return self.trees[path]
|
||||
|
||||
abspath = os.path.join(self.root, path)
|
||||
abspath = self.get_absolute_path(path)
|
||||
if not(os.path.exists(abspath) and os.path.isfile(abspath)):
|
||||
raise FailedCheck('File does not exist {!r}'.format(path))
|
||||
|
||||
|
@ -356,7 +362,7 @@ class CachedFiles(object):
|
|||
|
||||
def get_dir(self, path):
|
||||
path = self.resolve_path(path)
|
||||
abspath = os.path.join(self.root, path)
|
||||
abspath = self.get_absolute_path(path)
|
||||
if not(os.path.exists(abspath) and os.path.isdir(abspath)):
|
||||
raise FailedCheck('Directory does not exist {!r}'.format(path))
|
||||
|
||||
|
@ -538,6 +544,41 @@ def get_nb_matching_elements(cache, c, regexp, stop_at_first):
|
|||
return check_tree_text(cache.get_tree(c.args[0]), pat, c.args[2], regexp, stop_at_first)
|
||||
|
||||
|
||||
def check_files_in_folder(c, cache, folder, files):
|
||||
files = files.strip()
|
||||
if not files.startswith('[') or not files.endswith(']'):
|
||||
raise InvalidCheck("Expected list as second argument of @{} (ie '[]')".format(c.cmd))
|
||||
|
||||
folder = cache.get_absolute_path(folder)
|
||||
|
||||
# First we create a set of files to check if there are duplicates.
|
||||
files = shlex.split(files[1:-1].replace(",", ""))
|
||||
files_set = set()
|
||||
for file in files:
|
||||
if file in files_set:
|
||||
raise InvalidCheck("Duplicated file `{}` in @{}".format(file, c.cmd))
|
||||
files_set.add(file)
|
||||
folder_set = set([f for f in os.listdir(folder) if f != "." and f != ".."])
|
||||
|
||||
# Then we remove entries from both sets (we clone `folder_set` so we can iterate it while
|
||||
# removing its elements).
|
||||
for entry in set(folder_set):
|
||||
if entry in files_set:
|
||||
files_set.remove(entry)
|
||||
folder_set.remove(entry)
|
||||
|
||||
error = 0
|
||||
if len(files_set) != 0:
|
||||
print_err(c.lineno, c.context, "Entries not found in folder `{}`: `{}`".format(
|
||||
folder, files_set))
|
||||
error += 1
|
||||
if len(folder_set) != 0:
|
||||
print_err(c.lineno, c.context, "Extra entries in folder `{}`: `{}`".format(
|
||||
folder, folder_set))
|
||||
error += 1
|
||||
return error == 0
|
||||
|
||||
|
||||
ERR_COUNT = 0
|
||||
|
||||
|
||||
|
@ -566,6 +607,13 @@ def check_command(c, cache):
|
|||
else:
|
||||
raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd))
|
||||
|
||||
elif c.cmd == 'files': # check files in given folder
|
||||
if len(c.args) != 2: # @files <folder path> <file list>
|
||||
raise InvalidCheck("Invalid number of @{} arguments".format(c.cmd))
|
||||
elif c.negated:
|
||||
raise InvalidCheck("@{} doesn't support negative check".format(c.cmd))
|
||||
ret = check_files_in_folder(c, cache, c.args[0], c.args[1])
|
||||
|
||||
elif c.cmd == 'count': # count test
|
||||
if len(c.args) == 3: # @count <path> <pat> <count> = count test
|
||||
expected = int(c.args[2])
|
||||
|
|
|
@ -1361,8 +1361,10 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
|
|||
}
|
||||
|
||||
if let ty::TraitContainer = assoc_item.container {
|
||||
let bounds =
|
||||
tcx.explicit_item_bounds(assoc_item.def_id).subst_identity_iter_copied();
|
||||
let bounds = tcx
|
||||
.explicit_item_bounds(assoc_item.def_id)
|
||||
.subst_identity_iter_copied()
|
||||
.map(|(c, s)| (c.as_predicate(), s));
|
||||
let predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates;
|
||||
let predicates =
|
||||
tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied()));
|
||||
|
@ -2117,7 +2119,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
|
|||
|
||||
fn clean_middle_opaque_bounds<'tcx>(
|
||||
cx: &mut DocContext<'tcx>,
|
||||
bounds: Vec<ty::Predicate<'tcx>>,
|
||||
bounds: Vec<ty::Clause<'tcx>>,
|
||||
) -> Type {
|
||||
let mut regions = vec![];
|
||||
let mut has_sized = false;
|
||||
|
@ -2126,13 +2128,8 @@ fn clean_middle_opaque_bounds<'tcx>(
|
|||
.filter_map(|bound| {
|
||||
let bound_predicate = bound.kind();
|
||||
let trait_ref = match bound_predicate.skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr)) => {
|
||||
bound_predicate.rebind(tr.trait_ref)
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
|
||||
_ty,
|
||||
reg,
|
||||
))) => {
|
||||
ty::ClauseKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref),
|
||||
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
|
||||
if let Some(r) = clean_middle_region(reg) {
|
||||
regions.push(GenericBound::Outlives(r));
|
||||
}
|
||||
|
@ -2149,9 +2146,7 @@ fn clean_middle_opaque_bounds<'tcx>(
|
|||
let bindings: ThinVec<_> = bounds
|
||||
.iter()
|
||||
.filter_map(|bound| {
|
||||
if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) =
|
||||
bound.kind().skip_binder()
|
||||
{
|
||||
if let ty::ClauseKind::Projection(proj) = bound.kind().skip_binder() {
|
||||
if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() {
|
||||
Some(TypeBinding {
|
||||
assoc: projection_to_path_segment(
|
||||
|
|
|
@ -21,6 +21,7 @@ use rustc_middle::ty::{self, TyCtxt};
|
|||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
use std::fmt::Write as _;
|
||||
use std::mem;
|
||||
use std::sync::LazyLock as Lazy;
|
||||
use thin_vec::{thin_vec, ThinVec};
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -582,6 +583,8 @@ pub(crate) fn has_doc_flag(tcx: TyCtxt<'_>, did: DefId, flag: Symbol) -> bool {
|
|||
///
|
||||
/// Set by `bootstrap::Builder::doc_rust_lang_org_channel` in order to keep tests passing on beta/stable.
|
||||
pub(crate) const DOC_RUST_LANG_ORG_CHANNEL: &str = env!("DOC_RUST_LANG_ORG_CHANNEL");
|
||||
pub(crate) static DOC_CHANNEL: Lazy<&'static str> =
|
||||
Lazy::new(|| DOC_RUST_LANG_ORG_CHANNEL.rsplit("/").filter(|c| !c.is_empty()).next().unwrap());
|
||||
|
||||
/// Render a sequence of macro arms in a format suitable for displaying to the user
|
||||
/// as part of an item declaration.
|
||||
|
|
|
@ -55,6 +55,7 @@ struct PageLayout<'a> {
|
|||
sidebar: String,
|
||||
content: String,
|
||||
krate_with_trailing_slash: String,
|
||||
rust_channel: &'static str,
|
||||
pub(crate) rustdoc_version: &'a str,
|
||||
}
|
||||
|
||||
|
@ -82,6 +83,7 @@ pub(crate) fn render<T: Print, S: Print>(
|
|||
sidebar,
|
||||
content,
|
||||
krate_with_trailing_slash,
|
||||
rust_channel: *crate::clean::utils::DOC_CHANNEL,
|
||||
rustdoc_version,
|
||||
}
|
||||
.render()
|
||||
|
|
|
@ -1050,9 +1050,10 @@ function preLoadCss(cssUrl) {
|
|||
|
||||
function buildHelpMenu() {
|
||||
const book_info = document.createElement("span");
|
||||
const channel = getVar("channel");
|
||||
book_info.className = "top";
|
||||
book_info.innerHTML = "You can find more information in \
|
||||
<a href=\"https://doc.rust-lang.org/rustdoc/\">the rustdoc book</a>.";
|
||||
book_info.innerHTML = `You can find more information in \
|
||||
<a href="https://doc.rust-lang.org/${channel}/rustdoc/">the rustdoc book</a>.`;
|
||||
|
||||
const shortcuts = [
|
||||
["?", "Show this help dialog"],
|
||||
|
@ -1072,6 +1073,9 @@ function preLoadCss(cssUrl) {
|
|||
div_shortcuts.innerHTML = "<h2>Keyboard Shortcuts</h2><dl>" + shortcuts + "</dl></div>";
|
||||
|
||||
const infos = [
|
||||
`For a full list of all search features, take a look <a \
|
||||
href="https://doc.rust-lang.org/${channel}/rustdoc/how-to-read-rustdoc.html\
|
||||
#the-search-interface">here</a>.`,
|
||||
"Prefix searches with a type followed by a colon (e.g., <code>fn:</code>) to \
|
||||
restrict the search to a given item kind.",
|
||||
"Accepted kinds are: <code>fn</code>, <code>mod</code>, <code>struct</code>, \
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
data-themes="{{themes|join(",") }}" {#+ #}
|
||||
data-resource-suffix="{{page.resource_suffix}}" {#+ #}
|
||||
data-rustdoc-version="{{rustdoc_version}}" {#+ #}
|
||||
data-channel="{{rust_channel}}" {#+ #}
|
||||
data-search-js="{{files.search_js}}" {#+ #}
|
||||
data-settings-js="{{files.settings_js}}" {#+ #}
|
||||
data-settings-css="{{files.settings_css}}" {#+ #}
|
||||
|
|
|
@ -25,17 +25,21 @@ pub fn fail(s: &str) -> ! {
|
|||
detail_exit(1, cfg!(test));
|
||||
}
|
||||
|
||||
pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool {
|
||||
pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> Result<(), ()> {
|
||||
let status = match cmd.status() {
|
||||
Ok(status) => status,
|
||||
Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)),
|
||||
};
|
||||
if !status.success() && print_cmd_on_fail {
|
||||
println!(
|
||||
"\n\ncommand did not execute successfully: {:?}\n\
|
||||
expected success, got: {}\n\n",
|
||||
cmd, status
|
||||
);
|
||||
if !status.success() {
|
||||
if print_cmd_on_fail {
|
||||
println!(
|
||||
"\n\ncommand did not execute successfully: {:?}\n\
|
||||
expected success, got: {}\n\n",
|
||||
cmd, status
|
||||
);
|
||||
}
|
||||
Err(())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
status.success()
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
|
|||
let preds = cx.tcx.explicit_item_bounds(def_id);
|
||||
let mut is_future = false;
|
||||
for (p, _span) in preds.subst_iter_copied(cx.tcx, substs) {
|
||||
if let Some(trait_pred) = p.to_opt_poly_trait_pred() {
|
||||
if let Some(trait_pred) = p.as_trait_clause() {
|
||||
if Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() {
|
||||
is_future = true;
|
||||
break;
|
||||
|
|
|
@ -94,7 +94,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'
|
|||
match predicate.kind().skip_binder() {
|
||||
// For `impl Trait<U>`, it will register a predicate of `T: Trait<U>`, so we go through
|
||||
// and check substitutions to find `U`.
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
|
||||
ty::ClauseKind::Trait(trait_predicate) => {
|
||||
if trait_predicate
|
||||
.trait_ref
|
||||
.substs
|
||||
|
@ -107,7 +107,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'
|
|||
},
|
||||
// For `impl Trait<Assoc=U>`, it will register a predicate of `<T as Trait>::Assoc = U`,
|
||||
// so we check the term for `U`.
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection_predicate)) => {
|
||||
ty::ClauseKind::Projection(projection_predicate) => {
|
||||
if let ty::TermKind::Ty(ty) = projection_predicate.term.unpack() {
|
||||
if contains_ty_adt_constructor_opaque_inner(cx, ty, needle, seen) {
|
||||
return true;
|
||||
|
@ -268,7 +268,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
|
|||
ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)),
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
|
||||
for (predicate, _) in cx.tcx.explicit_item_bounds(def_id).skip_binder() {
|
||||
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder() {
|
||||
if let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() {
|
||||
if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) {
|
||||
return true;
|
||||
}
|
||||
|
@ -665,7 +665,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
|
|||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => sig_from_bounds(
|
||||
cx,
|
||||
ty,
|
||||
cx.tcx.item_bounds(def_id).subst(cx.tcx, substs),
|
||||
cx.tcx.item_bounds(def_id).subst_iter(cx.tcx, substs).map(|c| c.as_predicate()),
|
||||
cx.tcx.opt_parent(def_id),
|
||||
),
|
||||
ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)),
|
||||
|
@ -698,7 +698,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
|
|||
fn sig_from_bounds<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
predicates: &'tcx [Predicate<'tcx>],
|
||||
predicates: impl IntoIterator<Item = Predicate<'tcx>>,
|
||||
predicates_id: Option<DefId>,
|
||||
) -> Option<ExprFnSig<'tcx>> {
|
||||
let mut inputs = None;
|
||||
|
@ -747,7 +747,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option
|
|||
.subst_iter_copied(cx.tcx, ty.substs)
|
||||
{
|
||||
match pred.kind().skip_binder() {
|
||||
PredicateKind::Clause(ty::ClauseKind::Trait(p))
|
||||
ty::ClauseKind::Trait(p)
|
||||
if (lang_items.fn_trait() == Some(p.def_id())
|
||||
|| lang_items.fn_mut_trait() == Some(p.def_id())
|
||||
|| lang_items.fn_once_trait() == Some(p.def_id())) =>
|
||||
|
@ -760,7 +760,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option
|
|||
}
|
||||
inputs = Some(i);
|
||||
},
|
||||
PredicateKind::Clause(ty::ClauseKind::Projection(p))
|
||||
ty::ClauseKind::Projection(p)
|
||||
if Some(p.projection_ty.def_id) == lang_items.fn_once_output() =>
|
||||
{
|
||||
if output.is_some() {
|
||||
|
|
|
@ -67,7 +67,7 @@ fn find_librs<P: AsRef<Path>>(path: P) -> Option<PathBuf> {
|
|||
None
|
||||
}
|
||||
|
||||
fn main() {
|
||||
fn main() -> Result<(), ()> {
|
||||
let config = Arc::new(Config::from_args(env::args().collect()));
|
||||
|
||||
// The goal here is to check if the necessary packages are installed, and if not, we
|
||||
|
@ -128,7 +128,10 @@ If you want to install the `browser-ui-test` dependency, run `npm install browse
|
|||
}
|
||||
}
|
||||
|
||||
try_run(&mut cargo, config.verbose);
|
||||
if try_run(&mut cargo, config.verbose).is_err() {
|
||||
eprintln!("failed to document `{}`", entry.path().display());
|
||||
panic!("Cannot run rustdoc-gui tests");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,5 +161,5 @@ If you want to install the `browser-ui-test` dependency, run `npm install browse
|
|||
|
||||
command.args(&config.test_args);
|
||||
|
||||
try_run(&mut command, config.verbose);
|
||||
try_run(&mut command, config.verbose)
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use std::arch::asm;
|
|||
#[naked]
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn f() {
|
||||
// CHECK: define void @f()
|
||||
// CHECK: define {{(dso_local )?}}void @f()
|
||||
// CHECK-NEXT: start:
|
||||
// CHECK-NEXT: call void asm
|
||||
// CHECK-NEXT: unreachable
|
||||
|
|
|
@ -67,5 +67,5 @@ go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
|||
set-window-size: (1000, 1000) // Popover only appears when the screen width is >700px.
|
||||
assert-false: "#help"
|
||||
click: "#help-button > a"
|
||||
click: ".popover a[href='https://doc.rust-lang.org/rustdoc/']"
|
||||
wait-for-document-property: {"URL": "https://doc.rust-lang.org/rustdoc/"}
|
||||
click: "//*[@id='help']//a[text()='the rustdoc book']"
|
||||
wait-for-document-property: ({"URL": "https://doc.rust-lang.org/"}, STARTS_WITH)
|
||||
|
|
|
@ -31,7 +31,7 @@ define-function: (
|
|||
// color of the typename (struct, module, method, ...) before search results
|
||||
assert-css: (
|
||||
".result-name .typename",
|
||||
{"color": "#888"},
|
||||
{"color": |grey|},
|
||||
ALL,
|
||||
)
|
||||
},
|
||||
|
@ -75,6 +75,7 @@ store-value: (entry_color, "#0096cf") // color of the search entry
|
|||
store-value: (hover_entry_color, "#fff") // color of the hovered/focused search entry
|
||||
store-value: (background_color, "transparent") // background color
|
||||
store-value: (hover_background_color, "#3c3c3c") // hover background color
|
||||
store-value: (grey, "#999")
|
||||
|
||||
call-function: (
|
||||
"check-result-color", (
|
||||
|
@ -186,6 +187,7 @@ store-value: (entry_color, "#ddd") // color of the search entry
|
|||
store-value: (hover_entry_color, "#ddd") // color of the hovered/focused search entry
|
||||
store-value: (background_color, "transparent") // background color
|
||||
store-value: (hover_background_color, "#616161") // hover background color
|
||||
store-value: (grey, "#ccc")
|
||||
|
||||
call-function: (
|
||||
"check-result-color", (
|
||||
|
@ -282,6 +284,7 @@ store-value: (entry_color, "#000") // color of the search entry
|
|||
store-value: (hover_entry_color, "#000") // color of the hovered/focused search entry
|
||||
store-value: (background_color, "transparent") // background color
|
||||
store-value: (hover_background_color, "#ccc") // hover background color
|
||||
store-value: (grey, "#999")
|
||||
|
||||
call-function: (
|
||||
"check-result-color", (
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#![crate_name="foo"]
|
||||
|
||||
// @files foo '["index.html", "all.html", "sidebar-items.js"]'
|
||||
// @!has "foo/struct.Foo.html"
|
||||
#[doc(hidden)]
|
||||
pub struct Foo;
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
#![crate_name="foo"]
|
||||
|
||||
// @files "foo" \
|
||||
// '["index.html", "all.html", "sidebar-items.js", "foo", "bar", "private", "struct.Bar.html"]'
|
||||
// @files "foo/bar" '["index.html", "sidebar-items.js"]'
|
||||
|
||||
// @!has "foo/priv/index.html"
|
||||
// @!has "foo/priv/struct.Foo.html"
|
||||
mod private {
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
#![no_core]
|
||||
#![crate_name = "foo"]
|
||||
|
||||
// @files "foo" "['sidebar-items.js', 'all.html', 'hidden', 'index.html', 'struct.Bar.html', \
|
||||
// 'visible']"
|
||||
// @files "foo/hidden" "['inner']"
|
||||
// @files "foo/hidden/inner" "['trait.Foo.html']"
|
||||
// @files "foo/visible" "['index.html', 'sidebar-items.js', 'trait.Foo.html']"
|
||||
|
||||
// @!has 'foo/hidden/index.html'
|
||||
// @!has 'foo/hidden/inner/index.html'
|
||||
// FIXME: Should be `@!has`: https://github.com/rust-lang/rust/issues/111249
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
#![feature(no_core)]
|
||||
#![no_core]
|
||||
|
||||
// @files "foo" "['all.html', 'visible', 'index.html', 'sidebar-items.js', 'hidden', \
|
||||
// 'struct.Bar.html']"
|
||||
// @files "foo/visible" "['trait.Foo.html', 'index.html', 'sidebar-items.js']"
|
||||
// @files "foo/hidden" "['inner']"
|
||||
// @files "foo/hidden/inner" "['trait.Foo.html']"
|
||||
|
||||
// The following five should not fail!
|
||||
// @!has 'foo/hidden/index.html'
|
||||
// @!has 'foo/hidden/inner/index.html'
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// only-aarch64
|
||||
// run-pass
|
||||
// needs-asm-support
|
||||
// needs-unwind
|
||||
|
||||
#![feature(asm_unwind)]
|
||||
|
||||
|
|
11
tests/ui/closures/cannot-call-unsized-via-ptr-2.rs
Normal file
11
tests/ui/closures/cannot-call-unsized-via-ptr-2.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
#![feature(unsized_fn_params)]
|
||||
|
||||
fn main() {
|
||||
// CoerceMany "LUB"
|
||||
let f = if true { |_a| {} } else { |_b| {} };
|
||||
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
|
||||
//~| ERROR the size for values of type `[u8]` cannot be known at compilation time
|
||||
|
||||
let slice: Box<[u8]> = Box::new([1; 8]);
|
||||
f(*slice);
|
||||
}
|
21
tests/ui/closures/cannot-call-unsized-via-ptr-2.stderr
Normal file
21
tests/ui/closures/cannot-call-unsized-via-ptr-2.stderr
Normal file
|
@ -0,0 +1,21 @@
|
|||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||
--> $DIR/cannot-call-unsized-via-ptr-2.rs:5:24
|
||||
|
|
||||
LL | let f = if true { |_a| {} } else { |_b| {} };
|
||||
| ^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `[u8]`
|
||||
= note: all function arguments must have a statically known size
|
||||
|
||||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||
--> $DIR/cannot-call-unsized-via-ptr-2.rs:5:41
|
||||
|
|
||||
LL | let f = if true { |_a| {} } else { |_b| {} };
|
||||
| ^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `[u8]`
|
||||
= note: all function arguments must have a statically known size
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
10
tests/ui/closures/cannot-call-unsized-via-ptr.rs
Normal file
10
tests/ui/closures/cannot-call-unsized-via-ptr.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
#![feature(unsized_fn_params)]
|
||||
|
||||
fn main() {
|
||||
// Simple coercion
|
||||
let f: fn([u8]) = |_result| {};
|
||||
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
|
||||
|
||||
let slice: Box<[u8]> = Box::new([1; 8]);
|
||||
f(*slice);
|
||||
}
|
12
tests/ui/closures/cannot-call-unsized-via-ptr.stderr
Normal file
12
tests/ui/closures/cannot-call-unsized-via-ptr.stderr
Normal file
|
@ -0,0 +1,12 @@
|
|||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||
--> $DIR/cannot-call-unsized-via-ptr.rs:5:24
|
||||
|
|
||||
LL | let f: fn([u8]) = |_result| {};
|
||||
| ^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `[u8]`
|
||||
= note: all function arguments must have a statically known size
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -4,8 +4,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
|
|||
LL | unsafe { std::mem::transmute(v) }
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[[u32; 8888888]; 9999999]; 777777777]` are too big for the current architecture)
|
||||
= note: target type: `[[[u32; 9999999]; 777777777]; 239]` (59484438436515561504 bits)
|
||||
= note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture)
|
||||
= note: target type: `[[[u32; 9999999]; 777777777]; 239]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -43,8 +43,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
|
|||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[[u32; 8888888]; 9999999]; 777777777]` are too big for the current architecture)
|
||||
= note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[[u32; 9999999]; 777777777]; 8888888]` are too big for the current architecture)
|
||||
= note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture)
|
||||
= note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture)
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
|
25
tests/ui/consts/timeout.rs
Normal file
25
tests/ui/consts/timeout.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
//! This test checks that external macros don't hide
|
||||
//! the const eval timeout lint and then subsequently
|
||||
//! ICE.
|
||||
|
||||
// compile-flags: --crate-type=lib -Ztiny-const-eval-limit
|
||||
// error-pattern: constant evaluation is taking a long time
|
||||
|
||||
static ROOK_ATTACKS_TABLE: () = {
|
||||
0_u64.count_ones();
|
||||
0_u64.count_ones();
|
||||
0_u64.count_ones();
|
||||
0_u64.count_ones();
|
||||
0_u64.count_ones();
|
||||
0_u64.count_ones();
|
||||
0_u64.count_ones();
|
||||
0_u64.count_ones();
|
||||
0_u64.count_ones();
|
||||
0_u64.count_ones();
|
||||
0_u64.count_ones();
|
||||
0_u64.count_ones();
|
||||
0_u64.count_ones();
|
||||
0_u64.count_ones();
|
||||
0_u64.count_ones();
|
||||
0_u64.count_ones();
|
||||
};
|
15
tests/ui/consts/timeout.stderr
Normal file
15
tests/ui/consts/timeout.stderr
Normal file
|
@ -0,0 +1,15 @@
|
|||
error: constant evaluation is taking a long time
|
||||
--> $SRC_DIR/core/src/num/mod.rs:LL:COL
|
||||
|
|
||||
= note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval.
|
||||
If your compilation actually takes a long time, you can safely allow the lint.
|
||||
help: the constant being evaluated
|
||||
--> $DIR/timeout.rs:8:1
|
||||
|
|
||||
LL | static ROOK_ATTACKS_TABLE: () = {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: `#[deny(long_running_const_eval)]` on by default
|
||||
= note: this error originates in the macro `uint_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
@ -6,7 +6,7 @@ struct Struct {
|
|||
|
||||
fn new_struct(
|
||||
r: dyn A + 'static //~ ERROR the size for values of type
|
||||
) -> Struct { //~ ERROR the size for values of type
|
||||
) -> Struct {
|
||||
Struct { r: r }
|
||||
}
|
||||
|
||||
|
|
|
@ -15,22 +15,6 @@ help: function arguments must have a statically known size, borrowed types alway
|
|||
LL | r: &dyn A + 'static
|
||||
| +
|
||||
|
||||
error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time
|
||||
--> $DIR/issue-5883.rs:9:6
|
||||
|
|
||||
LL | ) -> Struct {
|
||||
| ^^^^^^ doesn't have a size known at compile-time
|
||||
LL | Struct { r: r }
|
||||
| --------------- this returned value is of type `Struct`
|
||||
|
|
||||
= help: within `Struct`, the trait `Sized` is not implemented for `(dyn A + 'static)`
|
||||
note: required because it appears within the type `Struct`
|
||||
--> $DIR/issue-5883.rs:3:8
|
||||
|
|
||||
LL | struct Struct {
|
||||
| ^^^^^^
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
22
tests/ui/layout/cannot-transmute-unnormalizable-type.rs
Normal file
22
tests/ui/layout/cannot-transmute-unnormalizable-type.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
trait Trait {
|
||||
type RefTarget;
|
||||
}
|
||||
|
||||
impl Trait for ()
|
||||
where
|
||||
Missing: Trait,
|
||||
//~^ ERROR cannot find type `Missing` in this scope
|
||||
{
|
||||
type RefTarget = ();
|
||||
}
|
||||
|
||||
struct Other {
|
||||
data: <() as Trait>::RefTarget,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
std::mem::transmute::<Option<()>, Option<&Other>>(None);
|
||||
//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
}
|
19
tests/ui/layout/cannot-transmute-unnormalizable-type.stderr
Normal file
19
tests/ui/layout/cannot-transmute-unnormalizable-type.stderr
Normal file
|
@ -0,0 +1,19 @@
|
|||
error[E0412]: cannot find type `Missing` in this scope
|
||||
--> $DIR/cannot-transmute-unnormalizable-type.rs:7:5
|
||||
|
|
||||
LL | Missing: Trait,
|
||||
| ^^^^^^^ not found in this scope
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/cannot-transmute-unnormalizable-type.rs:19:9
|
||||
|
|
||||
LL | std::mem::transmute::<Option<()>, Option<&Other>>(None);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `Option<()>` (8 bits)
|
||||
= note: target type: `Option<&Other>` (unable to determine layout for `Other` because `<() as Trait>::RefTarget` cannot be normalized)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0412, E0512.
|
||||
For more information about an error, try `rustc --explain E0412`.
|
|
@ -3,6 +3,7 @@
|
|||
// compile-flags: --test -Cpanic=abort -Zpanic-abort-tests=no
|
||||
// run-flags: --test-threads=1
|
||||
|
||||
// needs-unwind
|
||||
// ignore-wasm no panic or subprocess support
|
||||
// ignore-emscripten no panic or subprocess support
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
// compile-flags: --test
|
||||
// compile-flags: --test -Zpanic-abort-tests
|
||||
// run-flags: --test-threads=1
|
||||
// check-run-results
|
||||
// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
|
||||
// ignore-emscripten no threads support
|
||||
// needs-unwind
|
||||
// run-pass
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue