Auto merge of #110522 - matthiaskrgr:rollup-9m7rw3u, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #110432 (Report more detailed reason why `Index` impl is not satisfied) - #110451 (Minor changes to `IndexVec::ensure_contains_elem` & related methods) - #110476 (Delay a good path bug on drop for `TypeErrCtxt` (instead of a regular delayed bug)) - #110498 (Switch to `EarlyBinder` for `collect_return_position_impl_trait_in_trait_tys`) - #110507 (boostrap: print output during building tools) - #110510 (Fix ICE for transmutability in candidate assembly) - #110513 (make `non_upper_case_globals` lint not report trait impls) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
c781584079
@ -89,9 +89,9 @@ fn with_lctx(
|
||||
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
|
||||
|
||||
for (def_id, info) in lctx.children {
|
||||
self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
|
||||
debug_assert!(matches!(self.owners[def_id], hir::MaybeOwner::Phantom));
|
||||
self.owners[def_id] = info;
|
||||
let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
|
||||
debug_assert!(matches!(owner, hir::MaybeOwner::Phantom));
|
||||
*owner = info;
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,8 +99,8 @@ pub(super) fn lower_node(
|
||||
&mut self,
|
||||
def_id: LocalDefId,
|
||||
) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> {
|
||||
self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
|
||||
if let hir::MaybeOwner::Phantom = self.owners[def_id] {
|
||||
let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
|
||||
if let hir::MaybeOwner::Phantom = owner {
|
||||
let node = self.ast_index[def_id];
|
||||
match node {
|
||||
AstOwner::NonOwner => {}
|
||||
|
@ -368,8 +368,8 @@ fn index_crate<'a>(
|
||||
krate: &'a Crate,
|
||||
) -> IndexVec<LocalDefId, AstOwner<'a>> {
|
||||
let mut indexer = Indexer { node_id_to_def_id, index: IndexVec::new() };
|
||||
indexer.index.ensure_contains_elem(CRATE_DEF_ID, || AstOwner::NonOwner);
|
||||
indexer.index[CRATE_DEF_ID] = AstOwner::Crate(krate);
|
||||
*indexer.index.ensure_contains_elem(CRATE_DEF_ID, || AstOwner::NonOwner) =
|
||||
AstOwner::Crate(krate);
|
||||
visit::walk_crate(&mut indexer, krate);
|
||||
return indexer.index;
|
||||
|
||||
@ -386,22 +386,21 @@ fn visit_attribute(&mut self, _: &'a Attribute) {
|
||||
|
||||
fn visit_item(&mut self, item: &'a ast::Item) {
|
||||
let def_id = self.node_id_to_def_id[&item.id];
|
||||
self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner);
|
||||
self.index[def_id] = AstOwner::Item(item);
|
||||
*self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner) = AstOwner::Item(item);
|
||||
visit::walk_item(self, item)
|
||||
}
|
||||
|
||||
fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: visit::AssocCtxt) {
|
||||
let def_id = self.node_id_to_def_id[&item.id];
|
||||
self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner);
|
||||
self.index[def_id] = AstOwner::AssocItem(item, ctxt);
|
||||
*self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner) =
|
||||
AstOwner::AssocItem(item, ctxt);
|
||||
visit::walk_assoc_item(self, item, ctxt);
|
||||
}
|
||||
|
||||
fn visit_foreign_item(&mut self, item: &'a ast::ForeignItem) {
|
||||
let def_id = self.node_id_to_def_id[&item.id];
|
||||
self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner);
|
||||
self.index[def_id] = AstOwner::ForeignItem(item);
|
||||
*self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner) =
|
||||
AstOwner::ForeignItem(item);
|
||||
visit::walk_foreign_item(self, item);
|
||||
}
|
||||
}
|
||||
|
@ -579,7 +579,7 @@ fn compare_asyncness<'tcx>(
|
||||
pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
impl_m_def_id: LocalDefId,
|
||||
) -> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed> {
|
||||
) -> Result<&'tcx FxHashMap<DefId, ty::EarlyBinder<Ty<'tcx>>>, ErrorGuaranteed> {
|
||||
let impl_m = tcx.opt_associated_item(impl_m_def_id.to_def_id()).unwrap();
|
||||
let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap();
|
||||
let impl_trait_ref =
|
||||
@ -782,14 +782,14 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
||||
})
|
||||
});
|
||||
debug!(%ty);
|
||||
collected_tys.insert(def_id, ty);
|
||||
collected_tys.insert(def_id, ty::EarlyBinder(ty));
|
||||
}
|
||||
Err(err) => {
|
||||
let reported = tcx.sess.delay_span_bug(
|
||||
return_span,
|
||||
format!("could not fully resolve: {ty} => {err:?}"),
|
||||
);
|
||||
collected_tys.insert(def_id, tcx.ty_error(reported));
|
||||
collected_tys.insert(def_id, ty::EarlyBinder(tcx.ty_error(reported)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -251,7 +251,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
|
||||
match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) {
|
||||
Ok(map) => {
|
||||
let assoc_item = tcx.associated_item(def_id);
|
||||
return ty::EarlyBinder(map[&assoc_item.trait_item_def_id.unwrap()]);
|
||||
return map[&assoc_item.trait_item_def_id.unwrap()];
|
||||
}
|
||||
Err(_) => {
|
||||
return ty::EarlyBinder(tcx.ty_error_with_message(
|
||||
|
@ -38,6 +38,7 @@
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::DefineOpaqueTypes;
|
||||
use rustc_infer::infer::InferOk;
|
||||
use rustc_infer::traits::query::NoSolution;
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_middle::middle::stability;
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
|
||||
@ -53,6 +54,8 @@
|
||||
use rustc_target::abi::FieldIdx;
|
||||
use rustc_target::spec::abi::Abi::RustIntrinsic;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::traits::ObligationCtxt;
|
||||
use rustc_trait_selection::traits::{self, ObligationCauseCode};
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
@ -2800,6 +2803,17 @@ fn check_expr_index(
|
||||
element_ty
|
||||
}
|
||||
None => {
|
||||
// Attempt to *shallowly* search for an impl which matches,
|
||||
// but has nested obligations which are unsatisfied.
|
||||
for (base_t, _) in self.autoderef(base.span, base_t).silence_errors() {
|
||||
if let Some((_, index_ty, element_ty)) =
|
||||
self.find_and_report_unsatisfied_index_impl(expr.hir_id, base, base_t)
|
||||
{
|
||||
self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No);
|
||||
return element_ty;
|
||||
}
|
||||
}
|
||||
|
||||
let mut err = type_error_struct!(
|
||||
self.tcx.sess,
|
||||
expr.span,
|
||||
@ -2843,6 +2857,82 @@ fn check_expr_index(
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to match an implementation of `Index` against a self type, and report
|
||||
/// the unsatisfied predicates that result from confirming this impl.
|
||||
///
|
||||
/// Given an index expression, sometimes the `Self` type shallowly but does not
|
||||
/// deeply satisfy an impl predicate. Instead of simply saying that the type
|
||||
/// does not support being indexed, we want to point out exactly what nested
|
||||
/// predicates cause this to be, so that the user can add them to fix their code.
|
||||
fn find_and_report_unsatisfied_index_impl(
|
||||
&self,
|
||||
index_expr_hir_id: HirId,
|
||||
base_expr: &hir::Expr<'_>,
|
||||
base_ty: Ty<'tcx>,
|
||||
) -> Option<(ErrorGuaranteed, Ty<'tcx>, Ty<'tcx>)> {
|
||||
let index_trait_def_id = self.tcx.lang_items().index_trait()?;
|
||||
let index_trait_output_def_id = self.tcx.get_diagnostic_item(sym::IndexOutput)?;
|
||||
|
||||
let mut relevant_impls = vec![];
|
||||
self.tcx.for_each_relevant_impl(index_trait_def_id, base_ty, |impl_def_id| {
|
||||
relevant_impls.push(impl_def_id);
|
||||
});
|
||||
let [impl_def_id] = relevant_impls[..] else {
|
||||
// Only report unsatisfied impl predicates if there's one impl
|
||||
return None;
|
||||
};
|
||||
|
||||
self.commit_if_ok(|_| {
|
||||
let ocx = ObligationCtxt::new_in_snapshot(self);
|
||||
let impl_substs = self.fresh_substs_for_item(base_expr.span, impl_def_id);
|
||||
let impl_trait_ref =
|
||||
self.tcx.impl_trait_ref(impl_def_id).unwrap().subst(self.tcx, impl_substs);
|
||||
let cause = self.misc(base_expr.span);
|
||||
|
||||
// Match the impl self type against the base ty. If this fails,
|
||||
// we just skip this impl, since it's not particularly useful.
|
||||
let impl_trait_ref = ocx.normalize(&cause, self.param_env, impl_trait_ref);
|
||||
ocx.eq(&cause, self.param_env, impl_trait_ref.self_ty(), base_ty)?;
|
||||
|
||||
// Register the impl's predicates. One of these predicates
|
||||
// must be unsatisfied, or else we wouldn't have gotten here
|
||||
// in the first place.
|
||||
ocx.register_obligations(traits::predicates_for_generics(
|
||||
|idx, span| {
|
||||
traits::ObligationCause::new(
|
||||
base_expr.span,
|
||||
self.body_id,
|
||||
if span.is_dummy() {
|
||||
traits::ExprItemObligation(impl_def_id, index_expr_hir_id, idx)
|
||||
} else {
|
||||
traits::ExprBindingObligation(impl_def_id, span, index_expr_hir_id, idx)
|
||||
},
|
||||
)
|
||||
},
|
||||
self.param_env,
|
||||
self.tcx.predicates_of(impl_def_id).instantiate(self.tcx, impl_substs),
|
||||
));
|
||||
|
||||
// Normalize the output type, which we can use later on as the
|
||||
// return type of the index expression...
|
||||
let element_ty = ocx.normalize(
|
||||
&cause,
|
||||
self.param_env,
|
||||
self.tcx.mk_projection(index_trait_output_def_id, impl_trait_ref.substs),
|
||||
);
|
||||
|
||||
let errors = ocx.select_where_possible();
|
||||
// There should be at least one error reported. If not, we
|
||||
// will still delay a span bug in `report_fulfillment_errors`.
|
||||
Ok::<_, NoSolution>((
|
||||
self.err_ctxt().report_fulfillment_errors(&errors),
|
||||
impl_trait_ref.substs.type_at(1),
|
||||
element_ty,
|
||||
))
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
|
||||
fn point_at_index_if_possible(
|
||||
&self,
|
||||
errors: &mut Vec<traits::FulfillmentError<'tcx>>,
|
||||
|
@ -268,8 +268,7 @@ fn num_values(&self) -> usize {
|
||||
|
||||
fn node_mut(&mut self, id: PostOrderId) -> &mut NodeInfo {
|
||||
let size = self.num_values();
|
||||
self.nodes.ensure_contains_elem(id, || NodeInfo::new(size));
|
||||
&mut self.nodes[id]
|
||||
self.nodes.ensure_contains_elem(id, || NodeInfo::new(size))
|
||||
}
|
||||
|
||||
fn add_control_edge(&mut self, from: PostOrderId, to: PostOrderId) {
|
||||
|
@ -261,8 +261,7 @@ pub fn row(&self, row: R) -> Option<&IntervalSet<C>> {
|
||||
}
|
||||
|
||||
fn ensure_row(&mut self, row: R) -> &mut IntervalSet<C> {
|
||||
self.rows.ensure_contains_elem(row, || IntervalSet::new(self.column_size));
|
||||
&mut self.rows[row]
|
||||
self.rows.ensure_contains_elem(row, || IntervalSet::new(self.column_size))
|
||||
}
|
||||
|
||||
pub fn union_row(&mut self, row: R, from: &IntervalSet<C>) -> bool
|
||||
|
@ -236,12 +236,16 @@ pub fn convert_index_type<Ix: Idx>(self) -> IndexVec<Ix, T> {
|
||||
/// `elem`; if that is already true, then has no
|
||||
/// effect. Otherwise, inserts new values as needed by invoking
|
||||
/// `fill_value`.
|
||||
///
|
||||
/// Returns a reference to the `elem` entry.
|
||||
#[inline]
|
||||
pub fn ensure_contains_elem(&mut self, elem: I, fill_value: impl FnMut() -> T) {
|
||||
pub fn ensure_contains_elem(&mut self, elem: I, fill_value: impl FnMut() -> T) -> &mut T {
|
||||
let min_new_len = elem.index() + 1;
|
||||
if self.len() < min_new_len {
|
||||
self.raw.resize_with(min_new_len, fill_value);
|
||||
}
|
||||
|
||||
&mut self[elem]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -446,20 +450,17 @@ pub fn invert_bijective_mapping(&self) -> IndexVec<J, I> {
|
||||
impl<I: Idx, T> IndexVec<I, Option<T>> {
|
||||
#[inline]
|
||||
pub fn insert(&mut self, index: I, value: T) -> Option<T> {
|
||||
self.ensure_contains_elem(index, || None);
|
||||
self[index].replace(value)
|
||||
self.ensure_contains_elem(index, || None).replace(value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_or_insert_with(&mut self, index: I, value: impl FnOnce() -> T) -> &mut T {
|
||||
self.ensure_contains_elem(index, || None);
|
||||
self[index].get_or_insert_with(value)
|
||||
self.ensure_contains_elem(index, || None).get_or_insert_with(value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn remove(&mut self, index: I) -> Option<T> {
|
||||
self.ensure_contains_elem(index, || None);
|
||||
self[index].take()
|
||||
self.get_mut(index)?.take()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,6 @@
|
||||
self, error::TypeError, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
|
||||
TypeVisitable, TypeVisitableExt,
|
||||
};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
|
||||
use rustc_target::spec::abi;
|
||||
use std::ops::{ControlFlow, Deref};
|
||||
@ -138,7 +137,7 @@ fn drop(&mut self) {
|
||||
self.infcx
|
||||
.tcx
|
||||
.sess
|
||||
.delay_span_bug(DUMMY_SP, "used a `TypeErrCtxt` without failing compilation");
|
||||
.delay_good_path_bug("used a `TypeErrCtxt` without raising an error or lint");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -494,6 +494,15 @@ fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
|
||||
hir::ItemKind::Const(..) => {
|
||||
NonUpperCaseGlobals::check_upper_case(cx, "constant", &it.ident);
|
||||
}
|
||||
// we only want to check inherent associated consts, trait consts
|
||||
// are linted at def-site.
|
||||
hir::ItemKind::Impl(hir::Impl { of_trait: None, items, .. }) => {
|
||||
for it in *items {
|
||||
if let hir::AssocItemKind::Const = it.kind {
|
||||
NonUpperCaseGlobals::check_upper_case(cx, "associated constant", &it.ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@ -504,12 +513,6 @@ fn check_trait_item(&mut self, cx: &LateContext<'_>, ti: &hir::TraitItem<'_>) {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_impl_item(&mut self, cx: &LateContext<'_>, ii: &hir::ImplItem<'_>) {
|
||||
if let hir::ImplItemKind::Const(..) = ii.kind {
|
||||
NonUpperCaseGlobals::check_upper_case(cx, "associated constant", &ii.ident);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) {
|
||||
// Lint for constants that look like binding identifiers (#7526)
|
||||
if let PatKind::Path(hir::QPath::Resolved(None, ref path)) = p.kind {
|
||||
|
@ -416,7 +416,7 @@ fn encode(&self, buf: &mut FileEncoder) -> LazyTables {
|
||||
macro_definition: Table<DefIndex, LazyValue<ast::DelimArgs>>,
|
||||
proc_macro: Table<DefIndex, MacroKind>,
|
||||
deduced_param_attrs: Table<DefIndex, LazyArray<DeducedParamAttrs>>,
|
||||
trait_impl_trait_tys: Table<DefIndex, LazyValue<FxHashMap<DefId, Ty<'static>>>>,
|
||||
trait_impl_trait_tys: Table<DefIndex, LazyValue<FxHashMap<DefId, ty::EarlyBinder<Ty<'static>>>>>,
|
||||
doc_link_resolutions: Table<DefIndex, LazyValue<DocLinkResMap>>,
|
||||
doc_link_traits_in_scope: Table<DefIndex, LazyArray<DefId>>,
|
||||
}
|
||||
|
@ -413,8 +413,8 @@ pub(crate) fn set(&mut self, i: I, value: T) {
|
||||
// > Space requirements could perhaps be optimized by using the HAMT `popcnt`
|
||||
// > trick (i.e. divide things into buckets of 32 or 64 items and then
|
||||
// > store bit-masks of which item in each bucket is actually serialized).
|
||||
self.blocks.ensure_contains_elem(i, || [0; N]);
|
||||
value.write_to_bytes(&mut self.blocks[i]);
|
||||
let block = self.blocks.ensure_contains_elem(i, || [0; N]);
|
||||
value.write_to_bytes(block);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,11 @@ macro_rules! arena_types {
|
||||
|
||||
[] dep_kind: rustc_middle::dep_graph::DepKindStruct<'tcx>,
|
||||
|
||||
[decode] trait_impl_trait_tys: rustc_data_structures::fx::FxHashMap<rustc_hir::def_id::DefId, rustc_middle::ty::Ty<'tcx>>,
|
||||
[decode] trait_impl_trait_tys:
|
||||
rustc_data_structures::fx::FxHashMap<
|
||||
rustc_hir::def_id::DefId,
|
||||
rustc_middle::ty::EarlyBinder<rustc_middle::ty::Ty<'tcx>>
|
||||
>,
|
||||
[] bit_set_u32: rustc_index::bit_set::BitSet<u32>,
|
||||
[] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>,
|
||||
[decode] doc_link_resolutions: rustc_hir::def::DocLinkResMap,
|
||||
|
@ -181,7 +181,7 @@
|
||||
}
|
||||
|
||||
query collect_return_position_impl_trait_in_trait_tys(key: DefId)
|
||||
-> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed>
|
||||
-> Result<&'tcx FxHashMap<DefId, ty::EarlyBinder<Ty<'tcx>>>, ErrorGuaranteed>
|
||||
{
|
||||
desc { "comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process" }
|
||||
cache_on_disk_if { key.is_local() }
|
||||
|
@ -694,13 +694,6 @@ pub fn try_expand_impl_trait_type(
|
||||
if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) }
|
||||
}
|
||||
|
||||
pub fn bound_return_position_impl_trait_in_trait_tys(
|
||||
self,
|
||||
def_id: DefId,
|
||||
) -> ty::EarlyBinder<Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed>> {
|
||||
ty::EarlyBinder(self.collect_return_position_impl_trait_in_trait_tys(def_id))
|
||||
}
|
||||
|
||||
pub fn bound_explicit_item_bounds(
|
||||
self,
|
||||
def_id: DefId,
|
||||
|
@ -807,7 +807,9 @@ fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx FxHashMap<DefId, Ty<'tcx>> {
|
||||
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
|
||||
for &'tcx FxHashMap<DefId, ty::EarlyBinder<Ty<'tcx>>>
|
||||
{
|
||||
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
|
||||
RefDecodable::decode(d)
|
||||
}
|
||||
|
@ -204,6 +204,7 @@
|
||||
HashSet,
|
||||
Hasher,
|
||||
Implied,
|
||||
IndexOutput,
|
||||
Input,
|
||||
Into,
|
||||
IntoDiagnostic,
|
||||
|
@ -2277,11 +2277,10 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
|
||||
obligation.param_env,
|
||||
cause.clone(),
|
||||
obligation.recursion_depth + 1,
|
||||
tcx.bound_return_position_impl_trait_in_trait_tys(impl_fn_def_id)
|
||||
.map_bound(|tys| {
|
||||
tys.map_or_else(|guar| tcx.ty_error(guar), |tys| tys[&obligation.predicate.def_id])
|
||||
})
|
||||
.subst(tcx, impl_fn_substs),
|
||||
tcx.collect_return_position_impl_trait_in_trait_tys(impl_fn_def_id).map_or_else(
|
||||
|guar| tcx.ty_error(guar),
|
||||
|tys| tys[&obligation.predicate.def_id].subst(tcx, impl_fn_substs),
|
||||
),
|
||||
&mut obligations,
|
||||
);
|
||||
|
||||
|
@ -775,7 +775,7 @@ fn assemble_candidates_for_transmutability(
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
candidates: &mut SelectionCandidateSet<'tcx>,
|
||||
) {
|
||||
if obligation.has_non_region_param() {
|
||||
if obligation.predicate.has_non_region_param() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,7 @@
|
||||
pub trait Index<Idx: ?Sized> {
|
||||
/// The returned type after indexing.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "IndexOutput"]
|
||||
type Output: ?Sized;
|
||||
|
||||
/// Performs the indexing (`container[index]`) operation.
|
||||
|
@ -121,7 +121,7 @@ fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
|
||||
builder.info(&msg);
|
||||
|
||||
let mut cargo = Command::from(cargo);
|
||||
let is_expected = builder.try_run_quiet(&mut cargo);
|
||||
let is_expected = builder.try_run(&mut cargo);
|
||||
|
||||
builder.save_toolstate(
|
||||
tool,
|
||||
|
@ -1,5 +1,8 @@
|
||||
// Regression test for https://github.com/rust-lang/rust-clippy/issues/5207
|
||||
// compile-flags: --cap-lints=warn
|
||||
// ^ for https://github.com/rust-lang/rust-clippy/issues/10645
|
||||
|
||||
// Regression test for https://github.com/rust-lang/rust-clippy/issues/5207
|
||||
#![warn(clippy::future_not_send)]
|
||||
pub async fn bar<'a, T: 'a>(_: T) {}
|
||||
|
||||
fn main() {}
|
||||
|
16
src/tools/clippy/tests/ui/crashes/ice-5207.stderr
Normal file
16
src/tools/clippy/tests/ui/crashes/ice-5207.stderr
Normal file
@ -0,0 +1,16 @@
|
||||
warning: future cannot be sent between threads safely
|
||||
--> $DIR/ice-5207.rs:6:35
|
||||
|
|
||||
LL | pub async fn bar<'a, T: 'a>(_: T) {}
|
||||
| ^ future returned by `bar` is not `Send`
|
||||
|
|
||||
note: captured value is not `Send`
|
||||
--> $DIR/ice-5207.rs:6:29
|
||||
|
|
||||
LL | pub async fn bar<'a, T: 'a>(_: T) {}
|
||||
| ^ has type `T` which is not `Send`
|
||||
= note: `T` doesn't implement `std::marker::Send`
|
||||
= note: `-D clippy::future-not-send` implied by `-D warnings`
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
15
tests/ui/lint/lint-non-uppercase-trait-assoc-const.rs
Normal file
15
tests/ui/lint/lint-non-uppercase-trait-assoc-const.rs
Normal file
@ -0,0 +1,15 @@
|
||||
#![deny(non_upper_case_globals)]
|
||||
|
||||
trait Trait {
|
||||
const item: usize;
|
||||
//~^ ERROR associated constant `item` should have an upper case name [non_upper_case_globals]
|
||||
}
|
||||
|
||||
struct Foo;
|
||||
|
||||
impl Trait for Foo {
|
||||
const item: usize = 5;
|
||||
// ^^^ there should be no error here (in the trait `impl`)
|
||||
}
|
||||
|
||||
fn main() {}
|
14
tests/ui/lint/lint-non-uppercase-trait-assoc-const.stderr
Normal file
14
tests/ui/lint/lint-non-uppercase-trait-assoc-const.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error: associated constant `item` should have an upper case name
|
||||
--> $DIR/lint-non-uppercase-trait-assoc-const.rs:4:11
|
||||
|
|
||||
LL | const item: usize;
|
||||
| ^^^^ help: convert the identifier to upper case: `ITEM`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-non-uppercase-trait-assoc-const.rs:1:9
|
||||
|
|
||||
LL | #![deny(non_upper_case_globals)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
17
tests/ui/transmutability/issue-110467.rs
Normal file
17
tests/ui/transmutability/issue-110467.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// check-pass
|
||||
#![crate_type = "lib"]
|
||||
#![feature(transmutability)]
|
||||
use std::mem::BikeshedIntrinsicFrom;
|
||||
pub struct Context;
|
||||
|
||||
pub fn is_maybe_transmutable<Src, Dst>()
|
||||
where
|
||||
Dst: BikeshedIntrinsicFrom<Src, Context>,
|
||||
{
|
||||
}
|
||||
|
||||
// The `T` here should not have any effect on checking
|
||||
// if transmutability is allowed or not.
|
||||
fn function_with_generic<T>() {
|
||||
is_maybe_transmutable::<(), ()>();
|
||||
}
|
27
tests/ui/typeck/bad-index-due-to-nested.rs
Normal file
27
tests/ui/typeck/bad-index-due-to-nested.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use std::hash::Hash;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Index;
|
||||
|
||||
struct HashMap<K, V>(PhantomData<(K, V)>);
|
||||
|
||||
impl<K, V> Index<&K> for HashMap<K, V>
|
||||
where
|
||||
K: Hash,
|
||||
V: Copy,
|
||||
{
|
||||
type Output = V;
|
||||
|
||||
fn index(&self, k: &K) -> &V {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V {
|
||||
map[k]
|
||||
//~^ ERROR the trait bound `K: Hash` is not satisfied
|
||||
//~| ERROR the trait bound `V: Copy` is not satisfied
|
||||
//~| ERROR mismatched types
|
||||
//~| ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
64
tests/ui/typeck/bad-index-due-to-nested.stderr
Normal file
64
tests/ui/typeck/bad-index-due-to-nested.stderr
Normal file
@ -0,0 +1,64 @@
|
||||
error[E0277]: the trait bound `K: Hash` is not satisfied
|
||||
--> $DIR/bad-index-due-to-nested.rs:20:5
|
||||
|
|
||||
LL | map[k]
|
||||
| ^^^ the trait `Hash` is not implemented for `K`
|
||||
|
|
||||
note: required by a bound in `<HashMap<K, V> as Index<&K>>`
|
||||
--> $DIR/bad-index-due-to-nested.rs:9:8
|
||||
|
|
||||
LL | K: Hash,
|
||||
| ^^^^ required by this bound in `<HashMap<K, V> as Index<&K>>`
|
||||
help: consider restricting type parameter `K`
|
||||
|
|
||||
LL | fn index<'a, K: std::hash::Hash, V>(map: &'a HashMap<K, V>, k: K) -> &'a V {
|
||||
| +++++++++++++++++
|
||||
|
||||
error[E0277]: the trait bound `V: Copy` is not satisfied
|
||||
--> $DIR/bad-index-due-to-nested.rs:20:5
|
||||
|
|
||||
LL | map[k]
|
||||
| ^^^ the trait `Copy` is not implemented for `V`
|
||||
|
|
||||
note: required by a bound in `<HashMap<K, V> as Index<&K>>`
|
||||
--> $DIR/bad-index-due-to-nested.rs:10:8
|
||||
|
|
||||
LL | V: Copy,
|
||||
| ^^^^ required by this bound in `<HashMap<K, V> as Index<&K>>`
|
||||
help: consider restricting type parameter `V`
|
||||
|
|
||||
LL | fn index<'a, K, V: std::marker::Copy>(map: &'a HashMap<K, V>, k: K) -> &'a V {
|
||||
| +++++++++++++++++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/bad-index-due-to-nested.rs:20:9
|
||||
|
|
||||
LL | fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V {
|
||||
| - this type parameter
|
||||
LL | map[k]
|
||||
| ^
|
||||
| |
|
||||
| expected `&K`, found type parameter `K`
|
||||
| help: consider borrowing here: `&k`
|
||||
|
|
||||
= note: expected reference `&K`
|
||||
found type parameter `K`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/bad-index-due-to-nested.rs:20:5
|
||||
|
|
||||
LL | fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V {
|
||||
| - this type parameter ----- expected `&'a V` because of return type
|
||||
LL | map[k]
|
||||
| ^^^^^^
|
||||
| |
|
||||
| expected `&V`, found type parameter `V`
|
||||
| help: consider borrowing here: `&map[k]`
|
||||
|
|
||||
= note: expected reference `&'a V`
|
||||
found type parameter `V`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0308.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
Loading…
Reference in New Issue
Block a user