Auto merge of #109652 - matthiaskrgr:rollup-pbw3hi3, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #97506 (Stabilize `nonnull_slice_from_raw_parts`) - #98651 (Follow C-RW-VALUE in std::io::Cursor example) - #102742 (Remove unnecessary raw pointer in __rust_start_panic arg) - #109587 (Use an IndexVec to debug fingerprints.) - #109613 (fix type suggestions in match arms) - #109633 (Fix "Directly go to item in search if there is only one result" setting) - #109635 (debuginfo: Get pointer size/align from tcx.data_layout instead of layout_of) - #109641 (Don't elaborate non-obligations into obligations) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
553ecbe8ba
37 changed files with 235 additions and 181 deletions
|
@ -176,15 +176,14 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
||||||
|
|
||||||
return_if_di_node_created_in_meantime!(cx, unique_type_id);
|
return_if_di_node_created_in_meantime!(cx, unique_type_id);
|
||||||
|
|
||||||
let (thin_pointer_size, thin_pointer_align) =
|
let data_layout = &cx.tcx.data_layout;
|
||||||
cx.size_and_align_of(cx.tcx.mk_imm_ptr(cx.tcx.types.unit));
|
|
||||||
let ptr_type_debuginfo_name = compute_debuginfo_type_name(cx.tcx, ptr_type, true);
|
let ptr_type_debuginfo_name = compute_debuginfo_type_name(cx.tcx, ptr_type, true);
|
||||||
|
|
||||||
match fat_pointer_kind(cx, pointee_type) {
|
match fat_pointer_kind(cx, pointee_type) {
|
||||||
None => {
|
None => {
|
||||||
// This is a thin pointer. Create a regular pointer type and give it the correct name.
|
// This is a thin pointer. Create a regular pointer type and give it the correct name.
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(
|
||||||
(thin_pointer_size, thin_pointer_align),
|
(data_layout.pointer_size, data_layout.pointer_align.abi),
|
||||||
cx.size_and_align_of(ptr_type),
|
cx.size_and_align_of(ptr_type),
|
||||||
"ptr_type={}, pointee_type={}",
|
"ptr_type={}, pointee_type={}",
|
||||||
ptr_type,
|
ptr_type,
|
||||||
|
@ -195,8 +194,8 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
||||||
llvm::LLVMRustDIBuilderCreatePointerType(
|
llvm::LLVMRustDIBuilderCreatePointerType(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
pointee_type_di_node,
|
pointee_type_di_node,
|
||||||
thin_pointer_size.bits(),
|
data_layout.pointer_size.bits(),
|
||||||
thin_pointer_align.bits() as u32,
|
data_layout.pointer_align.abi.bits() as u32,
|
||||||
0, // Ignore DWARF address space.
|
0, // Ignore DWARF address space.
|
||||||
ptr_type_debuginfo_name.as_ptr().cast(),
|
ptr_type_debuginfo_name.as_ptr().cast(),
|
||||||
ptr_type_debuginfo_name.len(),
|
ptr_type_debuginfo_name.len(),
|
||||||
|
|
|
@ -1427,13 +1427,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
for (base_trait_ref, span, constness) in regular_traits_refs_spans {
|
for (base_trait_ref, span, constness) in regular_traits_refs_spans {
|
||||||
assert_eq!(constness, ty::BoundConstness::NotConst);
|
assert_eq!(constness, ty::BoundConstness::NotConst);
|
||||||
|
|
||||||
for obligation in traits::elaborate_trait_ref(tcx, base_trait_ref) {
|
for pred in traits::elaborate_trait_ref(tcx, base_trait_ref) {
|
||||||
debug!(
|
debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred);
|
||||||
"conv_object_ty_poly_trait_ref: observing object predicate `{:?}`",
|
|
||||||
obligation.predicate
|
|
||||||
);
|
|
||||||
|
|
||||||
let bound_predicate = obligation.predicate.kind();
|
let bound_predicate = pred.kind();
|
||||||
match bound_predicate.skip_binder() {
|
match bound_predicate.skip_binder() {
|
||||||
ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => {
|
ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => {
|
||||||
let pred = bound_predicate.rebind(pred);
|
let pred = bound_predicate.rebind(pred);
|
||||||
|
|
|
@ -1912,14 +1912,13 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
|
||||||
// Check elaborated bounds.
|
// Check elaborated bounds.
|
||||||
let implied_obligations = traits::elaborate_predicates_with_span(tcx, predicates_with_span);
|
let implied_obligations = traits::elaborate_predicates_with_span(tcx, predicates_with_span);
|
||||||
|
|
||||||
for obligation in implied_obligations {
|
for (pred, obligation_span) in implied_obligations {
|
||||||
// We lower empty bounds like `Vec<dyn Copy>:` as
|
// We lower empty bounds like `Vec<dyn Copy>:` as
|
||||||
// `WellFormed(Vec<dyn Copy>)`, which will later get checked by
|
// `WellFormed(Vec<dyn Copy>)`, which will later get checked by
|
||||||
// regular WF checking
|
// regular WF checking
|
||||||
if let ty::PredicateKind::WellFormed(..) = obligation.predicate.kind().skip_binder() {
|
if let ty::PredicateKind::WellFormed(..) = pred.kind().skip_binder() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let pred = obligation.predicate;
|
|
||||||
// Match the existing behavior.
|
// Match the existing behavior.
|
||||||
if pred.is_global() && !pred.has_late_bound_vars() {
|
if pred.is_global() && !pred.has_late_bound_vars() {
|
||||||
let pred = self.normalize(span, None, pred);
|
let pred = self.normalize(span, None, pred);
|
||||||
|
@ -1930,8 +1929,6 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
|
||||||
if let Some(hir::Generics { predicates, .. }) =
|
if let Some(hir::Generics { predicates, .. }) =
|
||||||
hir_node.and_then(|node| node.generics())
|
hir_node.and_then(|node| node.generics())
|
||||||
{
|
{
|
||||||
let obligation_span = obligation.cause.span();
|
|
||||||
|
|
||||||
span = predicates
|
span = predicates
|
||||||
.iter()
|
.iter()
|
||||||
// There seems to be no better way to find out which predicate we are in
|
// There seems to be no better way to find out which predicate we are in
|
||||||
|
|
|
@ -130,12 +130,9 @@ pub(super) fn item_bounds(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
) -> ty::EarlyBinder<&'_ ty::List<ty::Predicate<'_>>> {
|
) -> ty::EarlyBinder<&'_ ty::List<ty::Predicate<'_>>> {
|
||||||
let bounds = tcx.mk_predicates_from_iter(
|
let bounds = tcx.mk_predicates_from_iter(util::elaborate_predicates(
|
||||||
util::elaborate_predicates(
|
tcx,
|
||||||
tcx,
|
tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound),
|
||||||
tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound),
|
));
|
||||||
)
|
|
||||||
.map(|obligation| obligation.predicate),
|
|
||||||
);
|
|
||||||
ty::EarlyBinder(bounds)
|
ty::EarlyBinder(bounds)
|
||||||
}
|
}
|
||||||
|
|
|
@ -318,16 +318,8 @@ fn check_predicates<'tcx>(
|
||||||
span: Span,
|
span: Span,
|
||||||
) {
|
) {
|
||||||
let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs);
|
let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs);
|
||||||
let impl1_predicates: Vec<_> = traits::elaborate_predicates_with_span(
|
let impl1_predicates: Vec<_> =
|
||||||
tcx,
|
traits::elaborate_predicates_with_span(tcx, instantiated.into_iter()).collect();
|
||||||
std::iter::zip(
|
|
||||||
instantiated.predicates,
|
|
||||||
// Don't drop predicates (unsound!) because `spans` is too short
|
|
||||||
instantiated.spans.into_iter().chain(std::iter::repeat(span)),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.map(|obligation| (obligation.predicate, obligation.cause.span))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut impl2_predicates = if impl2_node.is_from_trait() {
|
let mut impl2_predicates = if impl2_node.is_from_trait() {
|
||||||
// Always applicable traits have to be always applicable without any
|
// Always applicable traits have to be always applicable without any
|
||||||
|
@ -341,7 +333,6 @@ fn check_predicates<'tcx>(
|
||||||
.predicates
|
.predicates
|
||||||
.into_iter(),
|
.into_iter(),
|
||||||
)
|
)
|
||||||
.map(|obligation| obligation.predicate)
|
|
||||||
.collect()
|
.collect()
|
||||||
};
|
};
|
||||||
debug!(?impl1_predicates, ?impl2_predicates);
|
debug!(?impl1_predicates, ?impl2_predicates);
|
||||||
|
@ -361,12 +352,16 @@ fn check_predicates<'tcx>(
|
||||||
// which is sound because we forbid impls like the following
|
// which is sound because we forbid impls like the following
|
||||||
//
|
//
|
||||||
// impl<D: Debug> AlwaysApplicable for D { }
|
// impl<D: Debug> AlwaysApplicable for D { }
|
||||||
let always_applicable_traits = impl1_predicates.iter().copied().filter(|&(predicate, _)| {
|
let always_applicable_traits = impl1_predicates
|
||||||
matches!(
|
.iter()
|
||||||
trait_predicate_kind(tcx, predicate),
|
.copied()
|
||||||
Some(TraitSpecializationKind::AlwaysApplicable)
|
.filter(|&(predicate, _)| {
|
||||||
)
|
matches!(
|
||||||
});
|
trait_predicate_kind(tcx, predicate),
|
||||||
|
Some(TraitSpecializationKind::AlwaysApplicable)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.map(|(pred, _span)| pred);
|
||||||
|
|
||||||
// Include the well-formed predicates of the type parameters of the impl.
|
// Include the well-formed predicates of the type parameters of the impl.
|
||||||
for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().subst_identity().substs {
|
for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().subst_identity().substs {
|
||||||
|
@ -380,10 +375,7 @@ fn check_predicates<'tcx>(
|
||||||
traits::elaborate_obligations(tcx, obligations).map(|obligation| obligation.predicate),
|
traits::elaborate_obligations(tcx, obligations).map(|obligation| obligation.predicate),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
impl2_predicates.extend(
|
impl2_predicates.extend(traits::elaborate_predicates(tcx, always_applicable_traits));
|
||||||
traits::elaborate_predicates_with_span(tcx, always_applicable_traits)
|
|
||||||
.map(|obligation| obligation.predicate),
|
|
||||||
);
|
|
||||||
|
|
||||||
for (predicate, span) in impl1_predicates {
|
for (predicate, span) in impl1_predicates {
|
||||||
if !impl2_predicates.iter().any(|pred2| trait_predicates_eq(tcx, predicate, *pred2, span)) {
|
if !impl2_predicates.iter().any(|pred2| trait_predicates_eq(tcx, predicate, *pred2, span)) {
|
||||||
|
|
|
@ -204,15 +204,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let mut expected_sig = None;
|
let mut expected_sig = None;
|
||||||
let mut expected_kind = None;
|
let mut expected_kind = None;
|
||||||
|
|
||||||
for obligation in traits::elaborate_predicates_with_span(
|
for (pred, span) in traits::elaborate_predicates_with_span(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
// Reverse the obligations here, since `elaborate_*` uses a stack,
|
// Reverse the obligations here, since `elaborate_*` uses a stack,
|
||||||
// and we want to keep inference generally in the same order of
|
// and we want to keep inference generally in the same order of
|
||||||
// the registered obligations.
|
// the registered obligations.
|
||||||
predicates.rev(),
|
predicates.rev(),
|
||||||
) {
|
) {
|
||||||
debug!(?obligation.predicate);
|
debug!(?pred);
|
||||||
let bound_predicate = obligation.predicate.kind();
|
let bound_predicate = pred.kind();
|
||||||
|
|
||||||
// Given a Projection predicate, we can potentially infer
|
// Given a Projection predicate, we can potentially infer
|
||||||
// the complete signature.
|
// the complete signature.
|
||||||
|
@ -220,9 +220,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
&& let ty::PredicateKind::Clause(ty::Clause::Projection(proj_predicate)) = bound_predicate.skip_binder()
|
&& let ty::PredicateKind::Clause(ty::Clause::Projection(proj_predicate)) = bound_predicate.skip_binder()
|
||||||
{
|
{
|
||||||
let inferred_sig = self.normalize(
|
let inferred_sig = self.normalize(
|
||||||
obligation.cause.span,
|
span,
|
||||||
self.deduce_sig_from_projection(
|
self.deduce_sig_from_projection(
|
||||||
Some(obligation.cause.span),
|
Some(span),
|
||||||
bound_predicate.rebind(proj_predicate),
|
bound_predicate.rebind(proj_predicate),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -576,17 +576,13 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||||
|
|
||||||
traits::elaborate_predicates(self.tcx, predicates.predicates.iter().copied())
|
traits::elaborate_predicates(self.tcx, predicates.predicates.iter().copied())
|
||||||
// We don't care about regions here.
|
// We don't care about regions here.
|
||||||
.filter_map(|obligation| match obligation.predicate.kind().skip_binder() {
|
.filter_map(|pred| match pred.kind().skip_binder() {
|
||||||
ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred))
|
ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred))
|
||||||
if trait_pred.def_id() == sized_def_id =>
|
if trait_pred.def_id() == sized_def_id =>
|
||||||
{
|
{
|
||||||
let span = predicates
|
let span = predicates
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(
|
.find_map(|(p, span)| if p == pred { Some(span) } else { None })
|
||||||
|(p, span)| {
|
|
||||||
if p == obligation.predicate { Some(span) } else { None }
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.unwrap_or(rustc_span::DUMMY_SP);
|
.unwrap_or(rustc_span::DUMMY_SP);
|
||||||
Some((trait_pred, span))
|
Some((trait_pred, span))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1942,7 +1942,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
escaped
|
escaped
|
||||||
}
|
}
|
||||||
let mut err = struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str);
|
let mut err = struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str);
|
||||||
if let Some((expected, found)) = trace.values.ty() {
|
let values = self.resolve_vars_if_possible(trace.values);
|
||||||
|
if let Some((expected, found)) = values.ty() {
|
||||||
match (expected.kind(), found.kind()) {
|
match (expected.kind(), found.kind()) {
|
||||||
(ty::Tuple(_), ty::Tuple(_)) => {}
|
(ty::Tuple(_), ty::Tuple(_)) => {}
|
||||||
// If a tuple of length one was expected and the found expression has
|
// If a tuple of length one was expected and the found expression has
|
||||||
|
|
|
@ -74,44 +74,58 @@ pub struct Elaborator<'tcx> {
|
||||||
pub fn elaborate_trait_ref<'tcx>(
|
pub fn elaborate_trait_ref<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||||
) -> Elaborator<'tcx> {
|
) -> impl Iterator<Item = ty::Predicate<'tcx>> {
|
||||||
elaborate_predicates(tcx, std::iter::once(trait_ref.without_const().to_predicate(tcx)))
|
elaborate_predicates(tcx, std::iter::once(trait_ref.without_const().to_predicate(tcx)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn elaborate_trait_refs<'tcx>(
|
pub fn elaborate_trait_refs<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
|
trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
|
||||||
) -> Elaborator<'tcx> {
|
) -> impl Iterator<Item = ty::Predicate<'tcx>> {
|
||||||
let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate(tcx));
|
let predicates = trait_refs.map(move |trait_ref| trait_ref.without_const().to_predicate(tcx));
|
||||||
elaborate_predicates(tcx, predicates)
|
elaborate_predicates(tcx, predicates)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn elaborate_predicates<'tcx>(
|
pub fn elaborate_predicates<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
|
predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
|
||||||
) -> Elaborator<'tcx> {
|
) -> impl Iterator<Item = ty::Predicate<'tcx>> {
|
||||||
let obligations = predicates
|
elaborate_obligations(
|
||||||
.map(|predicate| {
|
tcx,
|
||||||
predicate_obligation(predicate, ty::ParamEnv::empty(), ObligationCause::dummy())
|
predicates
|
||||||
})
|
.map(|predicate| {
|
||||||
.collect();
|
Obligation::new(
|
||||||
elaborate_obligations(tcx, obligations)
|
tcx,
|
||||||
|
// We'll dump the cause/param-env later
|
||||||
|
ObligationCause::dummy(),
|
||||||
|
ty::ParamEnv::empty(),
|
||||||
|
predicate,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
.map(|obl| obl.predicate)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn elaborate_predicates_with_span<'tcx>(
|
pub fn elaborate_predicates_with_span<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
predicates: impl Iterator<Item = (ty::Predicate<'tcx>, Span)>,
|
predicates: impl Iterator<Item = (ty::Predicate<'tcx>, Span)>,
|
||||||
) -> Elaborator<'tcx> {
|
) -> impl Iterator<Item = (ty::Predicate<'tcx>, Span)> {
|
||||||
let obligations = predicates
|
elaborate_obligations(
|
||||||
.map(|(predicate, span)| {
|
tcx,
|
||||||
predicate_obligation(
|
predicates
|
||||||
predicate,
|
.map(|(predicate, span)| {
|
||||||
ty::ParamEnv::empty(),
|
Obligation::new(
|
||||||
ObligationCause::dummy_with_span(span),
|
tcx,
|
||||||
)
|
// We'll dump the cause/param-env later
|
||||||
})
|
ObligationCause::dummy_with_span(span),
|
||||||
.collect();
|
ty::ParamEnv::empty(),
|
||||||
elaborate_obligations(tcx, obligations)
|
predicate,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
.map(|obl| (obl.predicate, obl.cause.span))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn elaborate_obligations<'tcx>(
|
pub fn elaborate_obligations<'tcx>(
|
||||||
|
@ -141,10 +155,6 @@ impl<'tcx> Elaborator<'tcx> {
|
||||||
self.stack.extend(obligations.into_iter().filter(|o| self.visited.insert(o.predicate)));
|
self.stack.extend(obligations.into_iter().filter(|o| self.visited.insert(o.predicate)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn filter_to_traits(self) -> FilterToTraits<Self> {
|
|
||||||
FilterToTraits::new(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
|
fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
|
||||||
let tcx = self.visited.tcx;
|
let tcx = self.visited.tcx;
|
||||||
|
|
||||||
|
@ -325,20 +335,18 @@ impl<'tcx> Iterator for Elaborator<'tcx> {
|
||||||
// Supertrait iterator
|
// Supertrait iterator
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
pub type Supertraits<'tcx> = FilterToTraits<Elaborator<'tcx>>;
|
|
||||||
|
|
||||||
pub fn supertraits<'tcx>(
|
pub fn supertraits<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||||
) -> Supertraits<'tcx> {
|
) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> {
|
||||||
elaborate_trait_ref(tcx, trait_ref).filter_to_traits()
|
FilterToTraits::new(elaborate_trait_ref(tcx, trait_ref))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn transitive_bounds<'tcx>(
|
pub fn transitive_bounds<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
|
trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
|
||||||
) -> Supertraits<'tcx> {
|
) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> {
|
||||||
elaborate_trait_refs(tcx, bounds).filter_to_traits()
|
FilterToTraits::new(elaborate_trait_refs(tcx, trait_refs))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A specialized variant of `elaborate_trait_refs` that only elaborates trait references that may
|
/// A specialized variant of `elaborate_trait_refs` that only elaborates trait references that may
|
||||||
|
@ -393,12 +401,12 @@ impl<I> FilterToTraits<I> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx, I: Iterator<Item = PredicateObligation<'tcx>>> Iterator for FilterToTraits<I> {
|
impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
|
||||||
type Item = ty::PolyTraitRef<'tcx>;
|
type Item = ty::PolyTraitRef<'tcx>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
|
fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
|
||||||
while let Some(obligation) = self.base_iterator.next() {
|
while let Some(pred) = self.base_iterator.next() {
|
||||||
if let Some(data) = obligation.predicate.to_opt_poly_trait_pred() {
|
if let Some(data) = pred.to_opt_poly_trait_pred() {
|
||||||
return Some(data.map_bound(|t| t.trait_ref));
|
return Some(data.map_bound(|t| t.trait_ref));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,11 +258,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
||||||
cx.tcx,
|
cx.tcx,
|
||||||
cx.tcx.explicit_item_bounds(def).iter().cloned(),
|
cx.tcx.explicit_item_bounds(def).iter().cloned(),
|
||||||
)
|
)
|
||||||
.find_map(|obligation| {
|
.find_map(|(pred, _span)| {
|
||||||
// We only look at the `DefId`, so it is safe to skip the binder here.
|
// We only look at the `DefId`, so it is safe to skip the binder here.
|
||||||
if let ty::PredicateKind::Clause(ty::Clause::Trait(
|
if let ty::PredicateKind::Clause(ty::Clause::Trait(
|
||||||
ref poly_trait_predicate,
|
ref poly_trait_predicate,
|
||||||
)) = obligation.predicate.kind().skip_binder()
|
)) = pred.kind().skip_binder()
|
||||||
{
|
{
|
||||||
let def_id = poly_trait_predicate.trait_ref.def_id;
|
let def_id = poly_trait_predicate.trait_ref.def_id;
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
|
||||||
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
|
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
|
||||||
if traits::impossible_predicates(
|
if traits::impossible_predicates(
|
||||||
tcx,
|
tcx,
|
||||||
traits::elaborate_predicates(tcx, predicates).map(|o| o.predicate).collect(),
|
traits::elaborate_predicates(tcx, predicates).collect(),
|
||||||
) {
|
) {
|
||||||
trace!("ConstProp skipped for {:?}: found unsatisfiable predicates", def_id);
|
trace!("ConstProp skipped for {:?}: found unsatisfiable predicates", def_id);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -93,7 +93,7 @@ impl<'tcx> MirLint<'tcx> for ConstProp {
|
||||||
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
|
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
|
||||||
if traits::impossible_predicates(
|
if traits::impossible_predicates(
|
||||||
tcx,
|
tcx,
|
||||||
traits::elaborate_predicates(tcx, predicates).map(|o| o.predicate).collect(),
|
traits::elaborate_predicates(tcx, predicates).collect(),
|
||||||
) {
|
) {
|
||||||
trace!("ConstProp skipped for {:?}: found unsatisfiable predicates", def_id);
|
trace!("ConstProp skipped for {:?}: found unsatisfiable predicates", def_id);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1065,7 +1065,7 @@ pub(super) struct CurrentDepGraph<K: DepKind> {
|
||||||
/// This is used to verify that fingerprints do not change between the creation of a node
|
/// This is used to verify that fingerprints do not change between the creation of a node
|
||||||
/// and its recomputation.
|
/// and its recomputation.
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
fingerprints: Lock<FxHashMap<DepNode<K>, Fingerprint>>,
|
fingerprints: Lock<IndexVec<DepNodeIndex, Option<Fingerprint>>>,
|
||||||
|
|
||||||
/// Used to trap when a specific edge is added to the graph.
|
/// Used to trap when a specific edge is added to the graph.
|
||||||
/// This is used for debug purposes and is only active with `debug_assertions`.
|
/// This is used for debug purposes and is only active with `debug_assertions`.
|
||||||
|
@ -1151,7 +1151,7 @@ impl<K: DepKind> CurrentDepGraph<K> {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
forbidden_edge,
|
forbidden_edge,
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
fingerprints: Lock::new(Default::default()),
|
fingerprints: Lock::new(IndexVec::from_elem_n(None, new_node_count_estimate)),
|
||||||
total_read_count: AtomicU64::new(0),
|
total_read_count: AtomicU64::new(0),
|
||||||
total_duplicate_read_count: AtomicU64::new(0),
|
total_duplicate_read_count: AtomicU64::new(0),
|
||||||
node_intern_event_id,
|
node_intern_event_id,
|
||||||
|
@ -1163,14 +1163,8 @@ impl<K: DepKind> CurrentDepGraph<K> {
|
||||||
if let Some(forbidden_edge) = &self.forbidden_edge {
|
if let Some(forbidden_edge) = &self.forbidden_edge {
|
||||||
forbidden_edge.index_to_node.lock().insert(dep_node_index, key);
|
forbidden_edge.index_to_node.lock().insert(dep_node_index, key);
|
||||||
}
|
}
|
||||||
match self.fingerprints.lock().entry(key) {
|
let previous = *self.fingerprints.lock().get_or_insert_with(dep_node_index, || fingerprint);
|
||||||
Entry::Vacant(v) => {
|
assert_eq!(previous, fingerprint, "Unstable fingerprints for {:?}", key);
|
||||||
v.insert(fingerprint);
|
|
||||||
}
|
|
||||||
Entry::Occupied(o) => {
|
|
||||||
assert_eq!(*o.get(), fingerprint, "Unstable fingerprints for {:?}", key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes the node to the current dep-graph and allocates a `DepNodeIndex` for it.
|
/// Writes the node to the current dep-graph and allocates a `DepNodeIndex` for it.
|
||||||
|
|
|
@ -470,7 +470,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
for assumption in
|
for assumption in
|
||||||
elaborate_predicates(tcx, bounds.iter().map(|bound| bound.with_self_ty(tcx, self_ty)))
|
elaborate_predicates(tcx, bounds.iter().map(|bound| bound.with_self_ty(tcx, self_ty)))
|
||||||
{
|
{
|
||||||
match G::consider_object_bound_candidate(self, goal, assumption.predicate) {
|
match G::consider_object_bound_candidate(self, goal, assumption) {
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result })
|
candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result })
|
||||||
}
|
}
|
||||||
|
|
|
@ -349,8 +349,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||||
let normalized_preds = elaborate_predicates(
|
let normalized_preds = elaborate_predicates(
|
||||||
tcx,
|
tcx,
|
||||||
computed_preds.clone().chain(user_computed_preds.iter().cloned()),
|
computed_preds.clone().chain(user_computed_preds.iter().cloned()),
|
||||||
)
|
);
|
||||||
.map(|o| o.predicate);
|
|
||||||
new_env = ty::ParamEnv::new(
|
new_env = ty::ParamEnv::new(
|
||||||
tcx.mk_predicates_from_iter(normalized_preds),
|
tcx.mk_predicates_from_iter(normalized_preds),
|
||||||
param_env.reveal(),
|
param_env.reveal(),
|
||||||
|
|
|
@ -367,8 +367,8 @@ fn negative_impl_exists<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to prove a negative obligation exists for super predicates
|
// Try to prove a negative obligation exists for super predicates
|
||||||
for o in util::elaborate_predicates(infcx.tcx, iter::once(o.predicate)) {
|
for pred in util::elaborate_predicates(infcx.tcx, iter::once(o.predicate)) {
|
||||||
if resolve_negative_obligation(infcx.fork(), &o, body_def_id) {
|
if resolve_negative_obligation(infcx.fork(), &o.with(infcx.tcx, pred), body_def_id) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,15 +82,15 @@ pub fn recompute_applicable_impls<'tcx>(
|
||||||
|
|
||||||
let predicates =
|
let predicates =
|
||||||
tcx.predicates_of(obligation.cause.body_id.to_def_id()).instantiate_identity(tcx);
|
tcx.predicates_of(obligation.cause.body_id.to_def_id()).instantiate_identity(tcx);
|
||||||
for obligation in elaborate_predicates_with_span(tcx, predicates.into_iter()) {
|
for (pred, span) in elaborate_predicates_with_span(tcx, predicates.into_iter()) {
|
||||||
let kind = obligation.predicate.kind();
|
let kind = pred.kind();
|
||||||
if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = kind.skip_binder()
|
if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = kind.skip_binder()
|
||||||
&& param_env_candidate_may_apply(kind.rebind(trait_pred))
|
&& param_env_candidate_may_apply(kind.rebind(trait_pred))
|
||||||
{
|
{
|
||||||
if kind.rebind(trait_pred.trait_ref) == ty::TraitRef::identity(tcx, trait_pred.def_id()) {
|
if kind.rebind(trait_pred.trait_ref) == ty::TraitRef::identity(tcx, trait_pred.def_id()) {
|
||||||
ambiguities.push(Ambiguity::ParamEnv(tcx.def_span(trait_pred.def_id())))
|
ambiguities.push(Ambiguity::ParamEnv(tcx.def_span(trait_pred.def_id())))
|
||||||
} else {
|
} else {
|
||||||
ambiguities.push(Ambiguity::ParamEnv(obligation.cause.span))
|
ambiguities.push(Ambiguity::ParamEnv(span))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1624,8 +1624,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for obligation in super::elaborate_predicates(self.tcx, std::iter::once(cond)) {
|
for pred in super::elaborate_predicates(self.tcx, std::iter::once(cond)) {
|
||||||
let bound_predicate = obligation.predicate.kind();
|
let bound_predicate = pred.kind();
|
||||||
if let ty::PredicateKind::Clause(ty::Clause::Trait(implication)) =
|
if let ty::PredicateKind::Clause(ty::Clause::Trait(implication)) =
|
||||||
bound_predicate.skip_binder()
|
bound_predicate.skip_binder()
|
||||||
{
|
{
|
||||||
|
|
|
@ -66,7 +66,7 @@ pub use self::util::{expand_trait_aliases, TraitAliasExpander};
|
||||||
pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
|
pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
|
||||||
pub use self::util::{
|
pub use self::util::{
|
||||||
supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_type,
|
supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_type,
|
||||||
SupertraitDefIds, Supertraits,
|
SupertraitDefIds,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use self::chalk_fulfill::FulfillmentContext as ChalkFulfillmentContext;
|
pub use self::chalk_fulfill::FulfillmentContext as ChalkFulfillmentContext;
|
||||||
|
@ -267,9 +267,7 @@ pub fn normalize_param_env_or_error<'tcx>(
|
||||||
// and errors will get reported then; so outside of type inference we
|
// and errors will get reported then; so outside of type inference we
|
||||||
// can be sure that no errors should occur.
|
// can be sure that no errors should occur.
|
||||||
let mut predicates: Vec<_> =
|
let mut predicates: Vec<_> =
|
||||||
util::elaborate_predicates(tcx, unnormalized_env.caller_bounds().into_iter())
|
util::elaborate_predicates(tcx, unnormalized_env.caller_bounds().into_iter()).collect();
|
||||||
.map(|obligation| obligation.predicate)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
|
debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
|
||||||
|
|
||||||
|
|
|
@ -379,26 +379,24 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
||||||
// Search for a predicate like `Self : Sized` amongst the trait bounds.
|
// Search for a predicate like `Self : Sized` amongst the trait bounds.
|
||||||
let predicates = tcx.predicates_of(def_id);
|
let predicates = tcx.predicates_of(def_id);
|
||||||
let predicates = predicates.instantiate_identity(tcx).predicates;
|
let predicates = predicates.instantiate_identity(tcx).predicates;
|
||||||
elaborate_predicates(tcx, predicates.into_iter()).any(|obligation| {
|
elaborate_predicates(tcx, predicates.into_iter()).any(|pred| match pred.kind().skip_binder() {
|
||||||
match obligation.predicate.kind().skip_binder() {
|
ty::PredicateKind::Clause(ty::Clause::Trait(ref trait_pred)) => {
|
||||||
ty::PredicateKind::Clause(ty::Clause::Trait(ref trait_pred)) => {
|
trait_pred.def_id() == sized_def_id && trait_pred.self_ty().is_param(0)
|
||||||
trait_pred.def_id() == sized_def_id && trait_pred.self_ty().is_param(0)
|
|
||||||
}
|
|
||||||
ty::PredicateKind::Clause(ty::Clause::Projection(..))
|
|
||||||
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
|
|
||||||
| ty::PredicateKind::Subtype(..)
|
|
||||||
| ty::PredicateKind::Coerce(..)
|
|
||||||
| ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
|
|
||||||
| ty::PredicateKind::WellFormed(..)
|
|
||||||
| ty::PredicateKind::ObjectSafe(..)
|
|
||||||
| ty::PredicateKind::ClosureKind(..)
|
|
||||||
| ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..))
|
|
||||||
| ty::PredicateKind::ConstEvaluatable(..)
|
|
||||||
| ty::PredicateKind::ConstEquate(..)
|
|
||||||
| ty::PredicateKind::AliasRelate(..)
|
|
||||||
| ty::PredicateKind::Ambiguous
|
|
||||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => false,
|
|
||||||
}
|
}
|
||||||
|
ty::PredicateKind::Clause(ty::Clause::Projection(..))
|
||||||
|
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
|
||||||
|
| ty::PredicateKind::Subtype(..)
|
||||||
|
| ty::PredicateKind::Coerce(..)
|
||||||
|
| ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
|
||||||
|
| ty::PredicateKind::WellFormed(..)
|
||||||
|
| ty::PredicateKind::ObjectSafe(..)
|
||||||
|
| ty::PredicateKind::ClosureKind(..)
|
||||||
|
| ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..))
|
||||||
|
| ty::PredicateKind::ConstEvaluatable(..)
|
||||||
|
| ty::PredicateKind::ConstEquate(..)
|
||||||
|
| ty::PredicateKind::AliasRelate(..)
|
||||||
|
| ty::PredicateKind::Ambiguous
|
||||||
|
| ty::PredicateKind::TypeWellFormedFromEnv(..) => false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,9 +667,9 @@ fn object_ty_for_trait<'tcx>(
|
||||||
debug!(?trait_predicate);
|
debug!(?trait_predicate);
|
||||||
|
|
||||||
let mut elaborated_predicates: Vec<_> = elaborate_trait_ref(tcx, trait_ref)
|
let mut elaborated_predicates: Vec<_> = elaborate_trait_ref(tcx, trait_ref)
|
||||||
.filter_map(|obligation| {
|
.filter_map(|pred| {
|
||||||
debug!(?obligation);
|
debug!(?pred);
|
||||||
let pred = obligation.predicate.to_opt_poly_projection_pred()?;
|
let pred = pred.to_opt_poly_projection_pred()?;
|
||||||
Some(pred.map_bound(|p| {
|
Some(pred.map_bound(|p| {
|
||||||
ty::ExistentialPredicate::Projection(ty::ExistentialProjection::erase_self_ty(
|
ty::ExistentialPredicate::Projection(ty::ExistentialProjection::erase_self_ty(
|
||||||
tcx, p,
|
tcx, p,
|
||||||
|
|
|
@ -921,9 +921,9 @@ pub(crate) fn required_region_bounds<'tcx>(
|
||||||
assert!(!erased_self_ty.has_escaping_bound_vars());
|
assert!(!erased_self_ty.has_escaping_bound_vars());
|
||||||
|
|
||||||
traits::elaborate_predicates(tcx, predicates)
|
traits::elaborate_predicates(tcx, predicates)
|
||||||
.filter_map(|obligation| {
|
.filter_map(|pred| {
|
||||||
debug!(?obligation);
|
debug!(?pred);
|
||||||
match obligation.predicate.kind().skip_binder() {
|
match pred.kind().skip_binder() {
|
||||||
ty::PredicateKind::Clause(ty::Clause::Projection(..))
|
ty::PredicateKind::Clause(ty::Clause::Projection(..))
|
||||||
| ty::PredicateKind::Clause(ty::Clause::Trait(..))
|
| ty::PredicateKind::Clause(ty::Clause::Trait(..))
|
||||||
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
|
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
|
||||||
|
|
|
@ -135,7 +135,6 @@
|
||||||
#![feature(maybe_uninit_uninit_array)]
|
#![feature(maybe_uninit_uninit_array)]
|
||||||
#![feature(maybe_uninit_uninit_array_transpose)]
|
#![feature(maybe_uninit_uninit_array_transpose)]
|
||||||
#![cfg_attr(test, feature(new_uninit))]
|
#![cfg_attr(test, feature(new_uninit))]
|
||||||
#![feature(nonnull_slice_from_raw_parts)]
|
|
||||||
#![feature(pattern)]
|
#![feature(pattern)]
|
||||||
#![feature(pointer_byte_offsets)]
|
#![feature(pointer_byte_offsets)]
|
||||||
#![feature(provide_any)]
|
#![feature(provide_any)]
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#![feature(const_cow_is_borrowed)]
|
#![feature(const_cow_is_borrowed)]
|
||||||
#![feature(const_heap)]
|
#![feature(const_heap)]
|
||||||
#![feature(const_mut_refs)]
|
#![feature(const_mut_refs)]
|
||||||
#![feature(const_nonnull_slice_from_raw_parts)]
|
#![feature(const_slice_from_raw_parts_mut)]
|
||||||
#![feature(const_ptr_write)]
|
#![feature(const_ptr_write)]
|
||||||
#![feature(const_try)]
|
#![feature(const_try)]
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
|
@ -38,7 +38,6 @@
|
||||||
#![feature(const_default_impls)]
|
#![feature(const_default_impls)]
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![feature(const_str_from_utf8)]
|
#![feature(const_str_from_utf8)]
|
||||||
#![feature(nonnull_slice_from_raw_parts)]
|
|
||||||
#![feature(panic_update_hook)]
|
#![feature(panic_update_hook)]
|
||||||
#![feature(pointer_is_aligned)]
|
#![feature(pointer_is_aligned)]
|
||||||
#![feature(slice_flatten)]
|
#![feature(slice_flatten)]
|
||||||
|
|
|
@ -462,8 +462,6 @@ impl<T> NonNull<[T]> {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// #![feature(nonnull_slice_from_raw_parts)]
|
|
||||||
///
|
|
||||||
/// use std::ptr::NonNull;
|
/// use std::ptr::NonNull;
|
||||||
///
|
///
|
||||||
/// // create a slice pointer when starting out with a pointer to the first element
|
/// // create a slice pointer when starting out with a pointer to the first element
|
||||||
|
@ -475,8 +473,8 @@ impl<T> NonNull<[T]> {
|
||||||
///
|
///
|
||||||
/// (Note that this example artificially demonstrates a use of this method,
|
/// (Note that this example artificially demonstrates a use of this method,
|
||||||
/// but `let slice = NonNull::from(&x[..]);` would be a better way to write code like this.)
|
/// but `let slice = NonNull::from(&x[..]);` would be a better way to write code like this.)
|
||||||
#[unstable(feature = "nonnull_slice_from_raw_parts", issue = "71941")]
|
#[stable(feature = "nonnull_slice_from_raw_parts", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[rustc_const_unstable(feature = "const_nonnull_slice_from_raw_parts", issue = "71941")]
|
#[rustc_const_unstable(feature = "const_slice_from_raw_parts_mut", issue = "67456")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn slice_from_raw_parts(data: NonNull<T>, len: usize) -> Self {
|
pub const fn slice_from_raw_parts(data: NonNull<T>, len: usize) -> Self {
|
||||||
|
@ -494,7 +492,6 @@ impl<T> NonNull<[T]> {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// #![feature(nonnull_slice_from_raw_parts)]
|
|
||||||
/// use std::ptr::NonNull;
|
/// use std::ptr::NonNull;
|
||||||
///
|
///
|
||||||
/// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3);
|
/// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3);
|
||||||
|
@ -514,7 +511,7 @@ impl<T> NonNull<[T]> {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// #![feature(slice_ptr_get, nonnull_slice_from_raw_parts)]
|
/// #![feature(slice_ptr_get)]
|
||||||
/// use std::ptr::NonNull;
|
/// use std::ptr::NonNull;
|
||||||
///
|
///
|
||||||
/// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3);
|
/// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3);
|
||||||
|
@ -534,7 +531,7 @@ impl<T> NonNull<[T]> {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// #![feature(slice_ptr_get, nonnull_slice_from_raw_parts)]
|
/// #![feature(slice_ptr_get)]
|
||||||
/// use std::ptr::NonNull;
|
/// use std::ptr::NonNull;
|
||||||
///
|
///
|
||||||
/// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3);
|
/// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3);
|
||||||
|
@ -668,7 +665,7 @@ impl<T> NonNull<[T]> {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(slice_ptr_get, nonnull_slice_from_raw_parts)]
|
/// #![feature(slice_ptr_get)]
|
||||||
/// use std::ptr::NonNull;
|
/// use std::ptr::NonNull;
|
||||||
///
|
///
|
||||||
/// let x = &mut [1, 2, 4];
|
/// let x = &mut [1, 2, 4];
|
||||||
|
|
|
@ -15,7 +15,7 @@ type SetAbortMessageType = unsafe extern "C" fn(*const libc::c_char) -> ();
|
||||||
//
|
//
|
||||||
// Weakly resolve the symbol for android_set_abort_message. This function is only available
|
// Weakly resolve the symbol for android_set_abort_message. This function is only available
|
||||||
// for API >= 21.
|
// for API >= 21.
|
||||||
pub(crate) unsafe fn android_set_abort_message(payload: *mut &mut dyn BoxMeUp) {
|
pub(crate) unsafe fn android_set_abort_message(payload: &mut dyn BoxMeUp) {
|
||||||
let func_addr =
|
let func_addr =
|
||||||
libc::dlsym(libc::RTLD_DEFAULT, ANDROID_SET_ABORT_MESSAGE.as_ptr() as *const libc::c_char)
|
libc::dlsym(libc::RTLD_DEFAULT, ANDROID_SET_ABORT_MESSAGE.as_ptr() as *const libc::c_char)
|
||||||
as usize;
|
as usize;
|
||||||
|
@ -23,7 +23,7 @@ pub(crate) unsafe fn android_set_abort_message(payload: *mut &mut dyn BoxMeUp) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let payload = (*payload).get();
|
let payload = payload.get();
|
||||||
let msg = match payload.downcast_ref::<&'static str>() {
|
let msg = match payload.downcast_ref::<&'static str>() {
|
||||||
Some(msg) => msg.as_bytes(),
|
Some(msg) => msg.as_bytes(),
|
||||||
None => match payload.downcast_ref::<String>() {
|
None => match payload.downcast_ref::<String>() {
|
||||||
|
|
|
@ -29,7 +29,7 @@ pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Sen
|
||||||
|
|
||||||
// "Leak" the payload and shim to the relevant abort on the platform in question.
|
// "Leak" the payload and shim to the relevant abort on the platform in question.
|
||||||
#[rustc_std_internal_symbol]
|
#[rustc_std_internal_symbol]
|
||||||
pub unsafe fn __rust_start_panic(_payload: *mut &mut dyn BoxMeUp) -> u32 {
|
pub unsafe fn __rust_start_panic(_payload: &mut dyn BoxMeUp) -> u32 {
|
||||||
// Android has the ability to attach a message as part of the abort.
|
// Android has the ability to attach a message as part of the abort.
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
android::android_set_abort_message(_payload);
|
android::android_set_abort_message(_payload);
|
||||||
|
|
|
@ -99,8 +99,8 @@ pub unsafe extern "C" fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any
|
||||||
// Entry point for raising an exception, just delegates to the platform-specific
|
// Entry point for raising an exception, just delegates to the platform-specific
|
||||||
// implementation.
|
// implementation.
|
||||||
#[rustc_std_internal_symbol]
|
#[rustc_std_internal_symbol]
|
||||||
pub unsafe fn __rust_start_panic(payload: *mut &mut dyn BoxMeUp) -> u32 {
|
pub unsafe fn __rust_start_panic(payload: &mut dyn BoxMeUp) -> u32 {
|
||||||
let payload = Box::from_raw((*payload).take_box());
|
let payload = Box::from_raw(payload.take_box());
|
||||||
|
|
||||||
imp::panic(payload)
|
imp::panic(payload)
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut, SeekFrom};
|
||||||
/// use std::fs::File;
|
/// use std::fs::File;
|
||||||
///
|
///
|
||||||
/// // a library function we've written
|
/// // a library function we've written
|
||||||
/// fn write_ten_bytes_at_end<W: Write + Seek>(writer: &mut W) -> io::Result<()> {
|
/// fn write_ten_bytes_at_end<W: Write + Seek>(mut writer: W) -> io::Result<()> {
|
||||||
/// writer.seek(SeekFrom::End(-10))?;
|
/// writer.seek(SeekFrom::End(-10))?;
|
||||||
///
|
///
|
||||||
/// for i in 0..10 {
|
/// for i in 0..10 {
|
||||||
|
|
|
@ -292,7 +292,6 @@
|
||||||
#![feature(is_some_and)]
|
#![feature(is_some_and)]
|
||||||
#![feature(maybe_uninit_slice)]
|
#![feature(maybe_uninit_slice)]
|
||||||
#![feature(maybe_uninit_write_slice)]
|
#![feature(maybe_uninit_write_slice)]
|
||||||
#![feature(nonnull_slice_from_raw_parts)]
|
|
||||||
#![feature(panic_can_unwind)]
|
#![feature(panic_can_unwind)]
|
||||||
#![feature(panic_info_message)]
|
#![feature(panic_info_message)]
|
||||||
#![feature(panic_internals)]
|
#![feature(panic_internals)]
|
||||||
|
|
|
@ -46,12 +46,10 @@ extern "C" {
|
||||||
fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static);
|
fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(improper_ctypes)]
|
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
/// `payload` is passed through another layer of raw pointers as `&mut dyn Trait` is not
|
/// `BoxMeUp` lazily performs allocation only when needed (this avoids
|
||||||
/// FFI-safe. `BoxMeUp` lazily performs allocation only when needed (this avoids allocations
|
/// allocations when using the "abort" panic runtime).
|
||||||
/// when using the "abort" panic runtime).
|
fn __rust_start_panic(payload: &mut dyn BoxMeUp) -> u32;
|
||||||
fn __rust_start_panic(payload: *mut &mut dyn BoxMeUp) -> u32;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function is called by the panic runtime if FFI code catches a Rust
|
/// This function is called by the panic runtime if FFI code catches a Rust
|
||||||
|
@ -738,10 +736,7 @@ pub fn rust_panic_without_hook(payload: Box<dyn Any + Send>) -> ! {
|
||||||
/// yer breakpoints.
|
/// yer breakpoints.
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
#[cfg_attr(not(test), rustc_std_internal_symbol)]
|
#[cfg_attr(not(test), rustc_std_internal_symbol)]
|
||||||
fn rust_panic(mut msg: &mut dyn BoxMeUp) -> ! {
|
fn rust_panic(msg: &mut dyn BoxMeUp) -> ! {
|
||||||
let code = unsafe {
|
let code = unsafe { __rust_start_panic(msg) };
|
||||||
let obj = &mut msg as *mut &mut dyn BoxMeUp;
|
|
||||||
__rust_start_panic(obj)
|
|
||||||
};
|
|
||||||
rtabort!("failed to initiate panic, error {code}")
|
rtabort!("failed to initiate panic, error {code}")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1946,11 +1946,7 @@ function initSearch(rawSearchIndex) {
|
||||||
function showResults(results, go_to_first, filterCrates) {
|
function showResults(results, go_to_first, filterCrates) {
|
||||||
const search = searchState.outputElement();
|
const search = searchState.outputElement();
|
||||||
if (go_to_first || (results.others.length === 1
|
if (go_to_first || (results.others.length === 1
|
||||||
&& getSettingValue("go-to-only-result") === "true"
|
&& getSettingValue("go-to-only-result") === "true")
|
||||||
// By default, the search DOM element is "empty" (meaning it has no children not
|
|
||||||
// text content). Once a search has been run, it won't be empty, even if you press
|
|
||||||
// ESC or empty the search input (which also "cancels" the search).
|
|
||||||
&& (!search.firstChild || search.firstChild.innerText !== searchState.loadingText))
|
|
||||||
) {
|
) {
|
||||||
const elem = document.createElement("a");
|
const elem = document.createElement("a");
|
||||||
elem.href = results.others[0].href;
|
elem.href = results.others[0].href;
|
||||||
|
|
|
@ -124,9 +124,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
|
||||||
|
|
||||||
let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds().iter())
|
let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds().iter())
|
||||||
.filter(|p| !p.is_global())
|
.filter(|p| !p.is_global())
|
||||||
.filter_map(|obligation| {
|
.filter_map(|pred| {
|
||||||
// Note that we do not want to deal with qualified predicates here.
|
// Note that we do not want to deal with qualified predicates here.
|
||||||
match obligation.predicate.kind().no_bound_vars() {
|
match pred.kind().no_bound_vars() {
|
||||||
Some(ty::PredicateKind::Clause(ty::Clause::Trait(pred))) if pred.def_id() != sized_trait => {
|
Some(ty::PredicateKind::Clause(ty::Clause::Trait(pred))) if pred.def_id() != sized_trait => {
|
||||||
Some(pred)
|
Some(pred)
|
||||||
},
|
},
|
||||||
|
|
|
@ -2106,7 +2106,6 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool {
|
||||||
traits::impossible_predicates(
|
traits::impossible_predicates(
|
||||||
cx.tcx,
|
cx.tcx,
|
||||||
traits::elaborate_predicates(cx.tcx, predicates)
|
traits::elaborate_predicates(cx.tcx, predicates)
|
||||||
.map(|o| o.predicate)
|
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
63
tests/rustdoc-gui/setting-go-to-only-result.goml
Normal file
63
tests/rustdoc-gui/setting-go-to-only-result.goml
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
// Checks that the setting "Directly go to item in search if there is only one result " is working as expected.
|
||||||
|
|
||||||
|
define-function: (
|
||||||
|
"check-setting",
|
||||||
|
(storage_value, setting_attribute_value),
|
||||||
|
block {
|
||||||
|
assert-local-storage: {"rustdoc-go-to-only-result": |storage_value|}
|
||||||
|
click: "#settings-menu"
|
||||||
|
wait-for: "#settings"
|
||||||
|
assert-property: ("#go-to-only-result", {"checked": |setting_attribute_value|})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
goto: "file://" + |DOC_PATH| + "/lib2/index.html"
|
||||||
|
|
||||||
|
call-function: ("check-setting", {
|
||||||
|
"storage_value": null,
|
||||||
|
"setting_attribute_value": "false",
|
||||||
|
})
|
||||||
|
|
||||||
|
// By default, the search doesn't automatically go to the page if there is only one result.
|
||||||
|
goto: "file://" + |DOC_PATH| + "/lib2/index.html?search=HasALongTraitWithParams"
|
||||||
|
// It will timeout if the setting isn't working.
|
||||||
|
wait-for: "#search"
|
||||||
|
assert-document-property: ({"URL": "/lib2/index.html"}, CONTAINS)
|
||||||
|
|
||||||
|
// Now we change its value.
|
||||||
|
click: "#settings-menu"
|
||||||
|
wait-for: "#settings"
|
||||||
|
click: "#go-to-only-result"
|
||||||
|
assert-local-storage: {"rustdoc-go-to-only-result": "true"}
|
||||||
|
|
||||||
|
goto: "file://" + |DOC_PATH| + "/lib2/index.html"
|
||||||
|
// We enter it into the search.
|
||||||
|
write: (".search-input", "HasALongTraitWithParams")
|
||||||
|
wait-for-document-property: {"title": "HasALongTraitWithParams in lib2 - Rust"}
|
||||||
|
assert-document-property: ({"URL": "/lib2/struct.HasALongTraitWithParams.html"}, ENDS_WITH)
|
||||||
|
|
||||||
|
// We try again to see if it goes to the only result
|
||||||
|
goto: "file://" + |DOC_PATH| + "/lib2/index.html?search=HasALongTraitWithParams"
|
||||||
|
wait-for-document-property: {"title": "HasALongTraitWithParams in lib2 - Rust"}
|
||||||
|
assert-document-property: ({"URL": "/lib2/struct.HasALongTraitWithParams.html"}, ENDS_WITH)
|
||||||
|
|
||||||
|
// We check the settings
|
||||||
|
call-function: ("check-setting", {
|
||||||
|
"storage_value": "true",
|
||||||
|
"setting_attribute_value": "true",
|
||||||
|
})
|
||||||
|
|
||||||
|
// And now we re-disable the setting.
|
||||||
|
click: "#go-to-only-result"
|
||||||
|
assert-local-storage: {"rustdoc-go-to-only-result": "false"}
|
||||||
|
|
||||||
|
goto: "file://" + |DOC_PATH| + "/lib2/index.html?search=HasALongTraitWithParams"
|
||||||
|
// It will timeout if the setting isn't working.
|
||||||
|
wait-for: "#search"
|
||||||
|
assert-document-property: ({"URL": "/lib2/index.html"}, CONTAINS)
|
||||||
|
|
||||||
|
// And we check everything is back the way it was before.
|
||||||
|
call-function: ("check-setting", {
|
||||||
|
"storage_value": "false",
|
||||||
|
"setting_attribute_value": "false",
|
||||||
|
})
|
|
@ -10,3 +10,12 @@ fn main() {
|
||||||
let _: char = '人'; //~ ERROR mismatched types
|
let _: char = '人'; //~ ERROR mismatched types
|
||||||
let _: char = '\''; //~ ERROR mismatched types
|
let _: char = '\''; //~ ERROR mismatched types
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// regression test for https://github.com/rust-lang/rust/issues/109586
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn convert_c_to_str(c: char) {
|
||||||
|
match c {
|
||||||
|
'A' => {} //~ ERROR mismatched types
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -10,3 +10,12 @@ fn main() {
|
||||||
let _: char = "人"; //~ ERROR mismatched types
|
let _: char = "人"; //~ ERROR mismatched types
|
||||||
let _: char = "'"; //~ ERROR mismatched types
|
let _: char = "'"; //~ ERROR mismatched types
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// regression test for https://github.com/rust-lang/rust/issues/109586
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn convert_c_to_str(c: char) {
|
||||||
|
match c {
|
||||||
|
"A" => {} //~ ERROR mismatched types
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -37,6 +37,19 @@ help: if you meant to write a `char` literal, use single quotes
|
||||||
LL | let _: char = '\'';
|
LL | let _: char = '\'';
|
||||||
| ~~~~
|
| ~~~~
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/char-as-str-single.rs:18:9
|
||||||
|
|
|
||||||
|
LL | match c {
|
||||||
|
| - this expression has type `char`
|
||||||
|
LL | "A" => {}
|
||||||
|
| ^^^ expected `char`, found `&str`
|
||||||
|
|
|
||||||
|
help: if you meant to write a `char` literal, use single quotes
|
||||||
|
|
|
||||||
|
LL | 'A' => {}
|
||||||
|
| ~~~
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue