Auto merge of - matthiaskrgr:rollup-pbw3hi3, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 -  (Stabilize `nonnull_slice_from_raw_parts`)
 -  (Follow C-RW-VALUE in std::io::Cursor example)
 -  (Remove unnecessary raw pointer in __rust_start_panic arg)
 -  (Use an IndexVec to debug fingerprints.)
 -  (fix type suggestions in match arms)
 -  (Fix "Directly go to item in search if there is only one result" setting)
 -  (debuginfo: Get pointer size/align from tcx.data_layout instead of layout_of)
 -  (Don't elaborate non-obligations into obligations)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-03-27 10:44:27 +00:00
commit 553ecbe8ba
37 changed files with 235 additions and 181 deletions
compiler
rustc_codegen_llvm/src/debuginfo
rustc_hir_analysis/src
rustc_hir_typeck/src
rustc_infer/src
infer/error_reporting
traits
rustc_lint/src
rustc_mir_transform/src
rustc_query_system/src/dep_graph
rustc_trait_selection/src
library
alloc
src
tests
core/src/ptr
panic_abort/src
panic_unwind/src
std/src
src
librustdoc/html/static/js
tools/clippy
clippy_lints/src
clippy_utils/src
tests

@ -176,15 +176,14 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
return_if_di_node_created_in_meantime!(cx, unique_type_id);
let (thin_pointer_size, thin_pointer_align) =
cx.size_and_align_of(cx.tcx.mk_imm_ptr(cx.tcx.types.unit));
let data_layout = &cx.tcx.data_layout;
let ptr_type_debuginfo_name = compute_debuginfo_type_name(cx.tcx, ptr_type, true);
match fat_pointer_kind(cx, pointee_type) {
None => {
// This is a thin pointer. Create a regular pointer type and give it the correct name.
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),
"ptr_type={}, pointee_type={}",
ptr_type,
@ -195,8 +194,8 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
llvm::LLVMRustDIBuilderCreatePointerType(
DIB(cx),
pointee_type_di_node,
thin_pointer_size.bits(),
thin_pointer_align.bits() as u32,
data_layout.pointer_size.bits(),
data_layout.pointer_align.abi.bits() as u32,
0, // Ignore DWARF address space.
ptr_type_debuginfo_name.as_ptr().cast(),
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 {
assert_eq!(constness, ty::BoundConstness::NotConst);
for obligation in traits::elaborate_trait_ref(tcx, base_trait_ref) {
debug!(
"conv_object_ty_poly_trait_ref: observing object predicate `{:?}`",
obligation.predicate
);
for pred in traits::elaborate_trait_ref(tcx, base_trait_ref) {
debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred);
let bound_predicate = obligation.predicate.kind();
let bound_predicate = pred.kind();
match bound_predicate.skip_binder() {
ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => {
let pred = bound_predicate.rebind(pred);

@ -1912,14 +1912,13 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
// Check elaborated bounds.
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
// `WellFormed(Vec<dyn Copy>)`, which will later get checked by
// regular WF checking
if let ty::PredicateKind::WellFormed(..) = obligation.predicate.kind().skip_binder() {
if let ty::PredicateKind::WellFormed(..) = pred.kind().skip_binder() {
continue;
}
let pred = obligation.predicate;
// Match the existing behavior.
if pred.is_global() && !pred.has_late_bound_vars() {
let pred = self.normalize(span, None, pred);
@ -1930,8 +1929,6 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
if let Some(hir::Generics { predicates, .. }) =
hir_node.and_then(|node| node.generics())
{
let obligation_span = obligation.cause.span();
span = predicates
.iter()
// 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<'_>,
def_id: DefId,
) -> ty::EarlyBinder<&'_ ty::List<ty::Predicate<'_>>> {
let bounds = tcx.mk_predicates_from_iter(
util::elaborate_predicates(
tcx,
tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound),
)
.map(|obligation| obligation.predicate),
);
let bounds = tcx.mk_predicates_from_iter(util::elaborate_predicates(
tcx,
tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound),
));
ty::EarlyBinder(bounds)
}

@ -318,16 +318,8 @@ fn check_predicates<'tcx>(
span: Span,
) {
let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs);
let impl1_predicates: Vec<_> = traits::elaborate_predicates_with_span(
tcx,
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 impl1_predicates: Vec<_> =
traits::elaborate_predicates_with_span(tcx, instantiated.into_iter()).collect();
let mut impl2_predicates = if impl2_node.is_from_trait() {
// Always applicable traits have to be always applicable without any
@ -341,7 +333,6 @@ fn check_predicates<'tcx>(
.predicates
.into_iter(),
)
.map(|obligation| obligation.predicate)
.collect()
};
debug!(?impl1_predicates, ?impl2_predicates);
@ -361,12 +352,16 @@ fn check_predicates<'tcx>(
// which is sound because we forbid impls like the following
//
// impl<D: Debug> AlwaysApplicable for D { }
let always_applicable_traits = impl1_predicates.iter().copied().filter(|&(predicate, _)| {
matches!(
trait_predicate_kind(tcx, predicate),
Some(TraitSpecializationKind::AlwaysApplicable)
)
});
let always_applicable_traits = impl1_predicates
.iter()
.copied()
.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.
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),
)
}
impl2_predicates.extend(
traits::elaborate_predicates_with_span(tcx, always_applicable_traits)
.map(|obligation| obligation.predicate),
);
impl2_predicates.extend(traits::elaborate_predicates(tcx, always_applicable_traits));
for (predicate, span) in impl1_predicates {
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_kind = None;
for obligation in traits::elaborate_predicates_with_span(
for (pred, span) in traits::elaborate_predicates_with_span(
self.tcx,
// Reverse the obligations here, since `elaborate_*` uses a stack,
// and we want to keep inference generally in the same order of
// the registered obligations.
predicates.rev(),
) {
debug!(?obligation.predicate);
let bound_predicate = obligation.predicate.kind();
debug!(?pred);
let bound_predicate = pred.kind();
// Given a Projection predicate, we can potentially infer
// 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 inferred_sig = self.normalize(
obligation.cause.span,
span,
self.deduce_sig_from_projection(
Some(obligation.cause.span),
Some(span),
bound_predicate.rebind(proj_predicate),
),
);

@ -576,17 +576,13 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
traits::elaborate_predicates(self.tcx, predicates.predicates.iter().copied())
// 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))
if trait_pred.def_id() == sized_def_id =>
{
let span = predicates
.iter()
.find_map(
|(p, span)| {
if p == obligation.predicate { Some(span) } else { None }
},
)
.find_map(|(p, span)| if p == pred { Some(span) } else { None })
.unwrap_or(rustc_span::DUMMY_SP);
Some((trait_pred, span))
}

@ -1942,7 +1942,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
escaped
}
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()) {
(ty::Tuple(_), ty::Tuple(_)) => {}
// 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>(
tcx: TyCtxt<'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)))
}
pub fn elaborate_trait_refs<'tcx>(
tcx: TyCtxt<'tcx>,
trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
) -> Elaborator<'tcx> {
let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate(tcx));
) -> impl Iterator<Item = ty::Predicate<'tcx>> {
let predicates = trait_refs.map(move |trait_ref| trait_ref.without_const().to_predicate(tcx));
elaborate_predicates(tcx, predicates)
}
pub fn elaborate_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
) -> Elaborator<'tcx> {
let obligations = predicates
.map(|predicate| {
predicate_obligation(predicate, ty::ParamEnv::empty(), ObligationCause::dummy())
})
.collect();
elaborate_obligations(tcx, obligations)
) -> impl Iterator<Item = ty::Predicate<'tcx>> {
elaborate_obligations(
tcx,
predicates
.map(|predicate| {
Obligation::new(
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>(
tcx: TyCtxt<'tcx>,
predicates: impl Iterator<Item = (ty::Predicate<'tcx>, Span)>,
) -> Elaborator<'tcx> {
let obligations = predicates
.map(|(predicate, span)| {
predicate_obligation(
predicate,
ty::ParamEnv::empty(),
ObligationCause::dummy_with_span(span),
)
})
.collect();
elaborate_obligations(tcx, obligations)
) -> impl Iterator<Item = (ty::Predicate<'tcx>, Span)> {
elaborate_obligations(
tcx,
predicates
.map(|(predicate, span)| {
Obligation::new(
tcx,
// We'll dump the cause/param-env later
ObligationCause::dummy_with_span(span),
ty::ParamEnv::empty(),
predicate,
)
})
.collect(),
)
.map(|obl| (obl.predicate, obl.cause.span))
}
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)));
}
pub fn filter_to_traits(self) -> FilterToTraits<Self> {
FilterToTraits::new(self)
}
fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
let tcx = self.visited.tcx;
@ -325,20 +335,18 @@ impl<'tcx> Iterator for Elaborator<'tcx> {
// Supertrait iterator
///////////////////////////////////////////////////////////////////////////
pub type Supertraits<'tcx> = FilterToTraits<Elaborator<'tcx>>;
pub fn supertraits<'tcx>(
tcx: TyCtxt<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
) -> Supertraits<'tcx> {
elaborate_trait_ref(tcx, trait_ref).filter_to_traits()
) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> {
FilterToTraits::new(elaborate_trait_ref(tcx, trait_ref))
}
pub fn transitive_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
) -> Supertraits<'tcx> {
elaborate_trait_refs(tcx, bounds).filter_to_traits()
trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> {
FilterToTraits::new(elaborate_trait_refs(tcx, trait_refs))
}
/// 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>;
fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
while let Some(obligation) = self.base_iterator.next() {
if let Some(data) = obligation.predicate.to_opt_poly_trait_pred() {
while let Some(pred) = self.base_iterator.next() {
if let Some(data) = pred.to_opt_poly_trait_pred() {
return Some(data.map_bound(|t| t.trait_ref));
}
}

@ -258,11 +258,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
cx.tcx,
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.
if let ty::PredicateKind::Clause(ty::Clause::Trait(
ref poly_trait_predicate,
)) = obligation.predicate.kind().skip_binder()
)) = pred.kind().skip_binder()
{
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 });
if traits::impossible_predicates(
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);
return;

@ -93,7 +93,7 @@ impl<'tcx> MirLint<'tcx> for ConstProp {
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
if traits::impossible_predicates(
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);
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
/// and its recomputation.
#[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.
/// 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)]
forbidden_edge,
#[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_duplicate_read_count: AtomicU64::new(0),
node_intern_event_id,
@ -1163,14 +1163,8 @@ impl<K: DepKind> CurrentDepGraph<K> {
if let Some(forbidden_edge) = &self.forbidden_edge {
forbidden_edge.index_to_node.lock().insert(dep_node_index, key);
}
match self.fingerprints.lock().entry(key) {
Entry::Vacant(v) => {
v.insert(fingerprint);
}
Entry::Occupied(o) => {
assert_eq!(*o.get(), fingerprint, "Unstable fingerprints for {:?}", key);
}
}
let previous = *self.fingerprints.lock().get_or_insert_with(dep_node_index, || fingerprint);
assert_eq!(previous, fingerprint, "Unstable fingerprints for {:?}", key);
}
/// 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
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) => {
candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result })
}

@ -349,8 +349,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
let normalized_preds = elaborate_predicates(
tcx,
computed_preds.clone().chain(user_computed_preds.iter().cloned()),
)
.map(|o| o.predicate);
);
new_env = ty::ParamEnv::new(
tcx.mk_predicates_from_iter(normalized_preds),
param_env.reveal(),

@ -367,8 +367,8 @@ fn negative_impl_exists<'tcx>(
}
// Try to prove a negative obligation exists for super predicates
for o in util::elaborate_predicates(infcx.tcx, iter::once(o.predicate)) {
if resolve_negative_obligation(infcx.fork(), &o, body_def_id) {
for pred in util::elaborate_predicates(infcx.tcx, iter::once(o.predicate)) {
if resolve_negative_obligation(infcx.fork(), &o.with(infcx.tcx, pred), body_def_id) {
return true;
}
}

@ -82,15 +82,15 @@ pub fn recompute_applicable_impls<'tcx>(
let predicates =
tcx.predicates_of(obligation.cause.body_id.to_def_id()).instantiate_identity(tcx);
for obligation in elaborate_predicates_with_span(tcx, predicates.into_iter()) {
let kind = obligation.predicate.kind();
for (pred, span) in elaborate_predicates_with_span(tcx, predicates.into_iter()) {
let kind = pred.kind();
if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = kind.skip_binder()
&& param_env_candidate_may_apply(kind.rebind(trait_pred))
{
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())))
} 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)) {
let bound_predicate = obligation.predicate.kind();
for pred in super::elaborate_predicates(self.tcx, std::iter::once(cond)) {
let bound_predicate = pred.kind();
if let ty::PredicateKind::Clause(ty::Clause::Trait(implication)) =
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::{
supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_type,
SupertraitDefIds, Supertraits,
SupertraitDefIds,
};
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
// can be sure that no errors should occur.
let mut predicates: Vec<_> =
util::elaborate_predicates(tcx, unnormalized_env.caller_bounds().into_iter())
.map(|obligation| obligation.predicate)
.collect();
util::elaborate_predicates(tcx, unnormalized_env.caller_bounds().into_iter()).collect();
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.
let predicates = tcx.predicates_of(def_id);
let predicates = predicates.instantiate_identity(tcx).predicates;
elaborate_predicates(tcx, predicates.into_iter()).any(|obligation| {
match obligation.predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::Clause::Trait(ref trait_pred)) => {
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,
elaborate_predicates(tcx, predicates.into_iter()).any(|pred| match pred.kind().skip_binder() {
ty::PredicateKind::Clause(ty::Clause::Trait(ref trait_pred)) => {
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,
})
}
@ -669,9 +667,9 @@ fn object_ty_for_trait<'tcx>(
debug!(?trait_predicate);
let mut elaborated_predicates: Vec<_> = elaborate_trait_ref(tcx, trait_ref)
.filter_map(|obligation| {
debug!(?obligation);
let pred = obligation.predicate.to_opt_poly_projection_pred()?;
.filter_map(|pred| {
debug!(?pred);
let pred = pred.to_opt_poly_projection_pred()?;
Some(pred.map_bound(|p| {
ty::ExistentialPredicate::Projection(ty::ExistentialProjection::erase_self_ty(
tcx, p,

@ -921,9 +921,9 @@ pub(crate) fn required_region_bounds<'tcx>(
assert!(!erased_self_ty.has_escaping_bound_vars());
traits::elaborate_predicates(tcx, predicates)
.filter_map(|obligation| {
debug!(?obligation);
match obligation.predicate.kind().skip_binder() {
.filter_map(|pred| {
debug!(?pred);
match pred.kind().skip_binder() {
ty::PredicateKind::Clause(ty::Clause::Projection(..))
| ty::PredicateKind::Clause(ty::Clause::Trait(..))
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))

@ -135,7 +135,6 @@
#![feature(maybe_uninit_uninit_array)]
#![feature(maybe_uninit_uninit_array_transpose)]
#![cfg_attr(test, feature(new_uninit))]
#![feature(nonnull_slice_from_raw_parts)]
#![feature(pattern)]
#![feature(pointer_byte_offsets)]
#![feature(provide_any)]

@ -8,7 +8,7 @@
#![feature(const_cow_is_borrowed)]
#![feature(const_heap)]
#![feature(const_mut_refs)]
#![feature(const_nonnull_slice_from_raw_parts)]
#![feature(const_slice_from_raw_parts_mut)]
#![feature(const_ptr_write)]
#![feature(const_try)]
#![feature(core_intrinsics)]
@ -38,7 +38,6 @@
#![feature(const_default_impls)]
#![feature(const_trait_impl)]
#![feature(const_str_from_utf8)]
#![feature(nonnull_slice_from_raw_parts)]
#![feature(panic_update_hook)]
#![feature(pointer_is_aligned)]
#![feature(slice_flatten)]

@ -462,8 +462,6 @@ impl<T> NonNull<[T]> {
/// # Examples
///
/// ```rust
/// #![feature(nonnull_slice_from_raw_parts)]
///
/// use std::ptr::NonNull;
///
/// // 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,
/// 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")]
#[rustc_const_unstable(feature = "const_nonnull_slice_from_raw_parts", issue = "71941")]
#[stable(feature = "nonnull_slice_from_raw_parts", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_unstable(feature = "const_slice_from_raw_parts_mut", issue = "67456")]
#[must_use]
#[inline]
pub const fn slice_from_raw_parts(data: NonNull<T>, len: usize) -> Self {
@ -494,7 +492,6 @@ impl<T> NonNull<[T]> {
/// # Examples
///
/// ```rust
/// #![feature(nonnull_slice_from_raw_parts)]
/// use std::ptr::NonNull;
///
/// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3);
@ -514,7 +511,7 @@ impl<T> NonNull<[T]> {
/// # Examples
///
/// ```rust
/// #![feature(slice_ptr_get, nonnull_slice_from_raw_parts)]
/// #![feature(slice_ptr_get)]
/// use std::ptr::NonNull;
///
/// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3);
@ -534,7 +531,7 @@ impl<T> NonNull<[T]> {
/// # Examples
///
/// ```rust
/// #![feature(slice_ptr_get, nonnull_slice_from_raw_parts)]
/// #![feature(slice_ptr_get)]
/// use std::ptr::NonNull;
///
/// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3);
@ -668,7 +665,7 @@ impl<T> NonNull<[T]> {
/// # Examples
///
/// ```
/// #![feature(slice_ptr_get, nonnull_slice_from_raw_parts)]
/// #![feature(slice_ptr_get)]
/// use std::ptr::NonNull;
///
/// 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
// 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 =
libc::dlsym(libc::RTLD_DEFAULT, ANDROID_SET_ABORT_MESSAGE.as_ptr() as *const libc::c_char)
as usize;
@ -23,7 +23,7 @@ pub(crate) unsafe fn android_set_abort_message(payload: *mut &mut dyn BoxMeUp) {
return;
}
let payload = (*payload).get();
let payload = payload.get();
let msg = match payload.downcast_ref::<&'static str>() {
Some(msg) => msg.as_bytes(),
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.
#[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.
#[cfg(target_os = "android")]
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
// implementation.
#[rustc_std_internal_symbol]
pub unsafe fn __rust_start_panic(payload: *mut &mut dyn BoxMeUp) -> u32 {
let payload = Box::from_raw((*payload).take_box());
pub unsafe fn __rust_start_panic(payload: &mut dyn BoxMeUp) -> u32 {
let payload = Box::from_raw(payload.take_box());
imp::panic(payload)
}

@ -34,7 +34,7 @@ use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut, SeekFrom};
/// use std::fs::File;
///
/// // 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))?;
///
/// for i in 0..10 {

@ -292,7 +292,6 @@
#![feature(is_some_and)]
#![feature(maybe_uninit_slice)]
#![feature(maybe_uninit_write_slice)]
#![feature(nonnull_slice_from_raw_parts)]
#![feature(panic_can_unwind)]
#![feature(panic_info_message)]
#![feature(panic_internals)]

@ -46,12 +46,10 @@ extern "C" {
fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static);
}
#[allow(improper_ctypes)]
extern "Rust" {
/// `payload` is passed through another layer of raw pointers as `&mut dyn Trait` is not
/// FFI-safe. `BoxMeUp` lazily performs allocation only when needed (this avoids allocations
/// when using the "abort" panic runtime).
fn __rust_start_panic(payload: *mut &mut dyn BoxMeUp) -> u32;
/// `BoxMeUp` lazily performs allocation only when needed (this avoids
/// allocations when using the "abort" panic runtime).
fn __rust_start_panic(payload: &mut dyn BoxMeUp) -> u32;
}
/// 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.
#[inline(never)]
#[cfg_attr(not(test), rustc_std_internal_symbol)]
fn rust_panic(mut msg: &mut dyn BoxMeUp) -> ! {
let code = unsafe {
let obj = &mut msg as *mut &mut dyn BoxMeUp;
__rust_start_panic(obj)
};
fn rust_panic(msg: &mut dyn BoxMeUp) -> ! {
let code = unsafe { __rust_start_panic(msg) };
rtabort!("failed to initiate panic, error {code}")
}

@ -1946,11 +1946,7 @@ function initSearch(rawSearchIndex) {
function showResults(results, go_to_first, filterCrates) {
const search = searchState.outputElement();
if (go_to_first || (results.others.length === 1
&& 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))
&& getSettingValue("go-to-only-result") === "true")
) {
const elem = document.createElement("a");
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())
.filter(|p| !p.is_global())
.filter_map(|obligation| {
.filter_map(|pred| {
// 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(pred)
},

@ -2106,7 +2106,6 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool {
traits::impossible_predicates(
cx.tcx,
traits::elaborate_predicates(cx.tcx, predicates)
.map(|o| o.predicate)
.collect::<Vec<_>>(),
)
}

@ -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
}
// 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
}
// 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 = '\'';
| ~~~~
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`.