Use is_lang_item and as_lang_item instead of handrolling their logic
This commit is contained in:
@@ -5,7 +5,7 @@ use rustc_hir as hir;
|
||||
use rustc_hir::GenericArg;
|
||||
use rustc_hir::def::{DefKind, PartialRes, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::{span_bug, ty};
|
||||
use rustc_session::parse::add_feature_diagnostics;
|
||||
use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, sym};
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
@@ -590,14 +590,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
/// lowering of `async Fn()` bounds to desugar to another trait like `LendingFn`.
|
||||
fn map_trait_to_async_trait(&self, def_id: DefId) -> Option<DefId> {
|
||||
let lang_items = self.tcx.lang_items();
|
||||
if Some(def_id) == lang_items.fn_trait() {
|
||||
lang_items.async_fn_trait()
|
||||
} else if Some(def_id) == lang_items.fn_mut_trait() {
|
||||
lang_items.async_fn_mut_trait()
|
||||
} else if Some(def_id) == lang_items.fn_once_trait() {
|
||||
lang_items.async_fn_once_trait()
|
||||
} else {
|
||||
None
|
||||
match self.tcx.fn_trait_kind_from_def_id(def_id)? {
|
||||
ty::ClosureKind::Fn => lang_items.async_fn_trait(),
|
||||
ty::ClosureKind::FnMut => lang_items.async_fn_mut_trait(),
|
||||
ty::ClosureKind::FnOnce => lang_items.async_fn_once_trait(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1265,12 +1265,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
&& let CallKind::FnCall { fn_trait_id, self_ty } = kind
|
||||
&& let ty::Param(_) = self_ty.kind()
|
||||
&& ty == self_ty
|
||||
&& [
|
||||
self.infcx.tcx.lang_items().fn_once_trait(),
|
||||
self.infcx.tcx.lang_items().fn_mut_trait(),
|
||||
self.infcx.tcx.lang_items().fn_trait(),
|
||||
]
|
||||
.contains(&Some(fn_trait_id))
|
||||
&& self.infcx.tcx.fn_trait_kind_from_def_id(fn_trait_id).is_some()
|
||||
{
|
||||
// Do not suggest `F: FnOnce() + Clone`.
|
||||
false
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
use rustc_abi::ExternAbi;
|
||||
use rustc_errors::DiagMessage;
|
||||
use rustc_hir::{self as hir};
|
||||
use rustc_middle::bug;
|
||||
use rustc_hir::{self as hir, LangItem};
|
||||
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
@@ -173,23 +172,22 @@ pub(crate) fn check_intrinsic_type(
|
||||
ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv),
|
||||
]);
|
||||
let mk_va_list_ty = |mutbl| {
|
||||
tcx.lang_items().va_list().map(|did| {
|
||||
let region = ty::Region::new_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BoundRegionKind::Anon },
|
||||
);
|
||||
let env_region = ty::Region::new_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
ty::BoundRegion {
|
||||
var: ty::BoundVar::from_u32(2),
|
||||
kind: ty::BoundRegionKind::ClosureEnv,
|
||||
},
|
||||
);
|
||||
let va_list_ty = tcx.type_of(did).instantiate(tcx, &[region.into()]);
|
||||
(Ty::new_ref(tcx, env_region, va_list_ty, mutbl), va_list_ty)
|
||||
})
|
||||
let did = tcx.require_lang_item(LangItem::VaList, Some(span));
|
||||
let region = ty::Region::new_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BoundRegionKind::Anon },
|
||||
);
|
||||
let env_region = ty::Region::new_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
ty::BoundRegion {
|
||||
var: ty::BoundVar::from_u32(2),
|
||||
kind: ty::BoundRegionKind::ClosureEnv,
|
||||
},
|
||||
);
|
||||
let va_list_ty = tcx.type_of(did).instantiate(tcx, &[region.into()]);
|
||||
(Ty::new_ref(tcx, env_region, va_list_ty, mutbl), va_list_ty)
|
||||
};
|
||||
|
||||
let (n_tps, n_lts, n_cts, inputs, output, safety) = if name_str.starts_with("atomic_") {
|
||||
@@ -548,23 +546,17 @@ pub(crate) fn check_intrinsic_type(
|
||||
)
|
||||
}
|
||||
|
||||
sym::va_start | sym::va_end => match mk_va_list_ty(hir::Mutability::Mut) {
|
||||
Some((va_list_ref_ty, _)) => (0, 0, vec![va_list_ref_ty], tcx.types.unit),
|
||||
None => bug!("`va_list` lang item needed for C-variadic intrinsics"),
|
||||
},
|
||||
sym::va_start | sym::va_end => {
|
||||
(0, 0, vec![mk_va_list_ty(hir::Mutability::Mut).0], tcx.types.unit)
|
||||
}
|
||||
|
||||
sym::va_copy => match mk_va_list_ty(hir::Mutability::Not) {
|
||||
Some((va_list_ref_ty, va_list_ty)) => {
|
||||
let va_list_ptr_ty = Ty::new_mut_ptr(tcx, va_list_ty);
|
||||
(0, 0, vec![va_list_ptr_ty, va_list_ref_ty], tcx.types.unit)
|
||||
}
|
||||
None => bug!("`va_list` lang item needed for C-variadic intrinsics"),
|
||||
},
|
||||
sym::va_copy => {
|
||||
let (va_list_ref_ty, va_list_ty) = mk_va_list_ty(hir::Mutability::Not);
|
||||
let va_list_ptr_ty = Ty::new_mut_ptr(tcx, va_list_ty);
|
||||
(0, 0, vec![va_list_ptr_ty, va_list_ref_ty], tcx.types.unit)
|
||||
}
|
||||
|
||||
sym::va_arg => match mk_va_list_ty(hir::Mutability::Mut) {
|
||||
Some((va_list_ref_ty, _)) => (1, 0, vec![va_list_ref_ty], param(0)),
|
||||
None => bug!("`va_list` lang item needed for C-variadic intrinsics"),
|
||||
},
|
||||
sym::va_arg => (1, 0, vec![mk_va_list_ty(hir::Mutability::Mut).0], param(0)),
|
||||
|
||||
sym::nontemporal_store => {
|
||||
(1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit)
|
||||
|
||||
@@ -750,7 +750,7 @@ fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), Err
|
||||
ObligationCause::misc(impl_span, checker.impl_def_id),
|
||||
param_env,
|
||||
nontrivial_field_ty,
|
||||
tcx.lang_items().pointer_like().unwrap(),
|
||||
tcx.require_lang_item(LangItem::PointerLike, Some(impl_span)),
|
||||
);
|
||||
// FIXME(dyn-star): We should regionck this implementation.
|
||||
if ocx.select_all_or_error().is_empty() {
|
||||
|
||||
@@ -37,7 +37,7 @@ pub(crate) fn check_legal_trait_for_method_call(
|
||||
body_id: DefId,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
if tcx.is_lang_item(trait_id, LangItem::Drop)
|
||||
&& tcx.lang_items().fallback_surface_drop_fn() != Some(body_id)
|
||||
&& !tcx.is_lang_item(body_id, LangItem::FallbackSurfaceDrop)
|
||||
{
|
||||
let sugg = if let Some(receiver) = receiver.filter(|s| !s.is_empty()) {
|
||||
errors::ExplicitDestructorCallSugg::Snippet {
|
||||
|
||||
@@ -925,7 +925,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
let detect_dotdot = |err: &mut Diag<'_>, ty: Ty<'_>, expr: &hir::Expr<'_>| {
|
||||
if let ty::Adt(adt, _) = ty.kind()
|
||||
&& self.tcx().lang_items().get(hir::LangItem::RangeFull) == Some(adt.did())
|
||||
&& self.tcx().is_lang_item(adt.did(), hir::LangItem::RangeFull)
|
||||
&& let hir::ExprKind::Struct(
|
||||
hir::QPath::LangItem(hir::LangItem::RangeFull, _),
|
||||
[],
|
||||
|
||||
@@ -1457,15 +1457,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
_ => (None, None),
|
||||
};
|
||||
|
||||
let ranges = &[
|
||||
self.tcx.lang_items().range_struct(),
|
||||
self.tcx.lang_items().range_from_struct(),
|
||||
self.tcx.lang_items().range_to_struct(),
|
||||
self.tcx.lang_items().range_full_struct(),
|
||||
self.tcx.lang_items().range_inclusive_struct(),
|
||||
self.tcx.lang_items().range_to_inclusive_struct(),
|
||||
];
|
||||
if type_def_id != None && ranges.contains(&type_def_id) {
|
||||
let is_range = match type_def_id.and_then(|id| self.tcx.as_lang_item(id)) {
|
||||
Some(
|
||||
LangItem::Range
|
||||
| LangItem::RangeFrom
|
||||
| LangItem::RangeTo
|
||||
| LangItem::RangeFull
|
||||
| LangItem::RangeInclusiveStruct
|
||||
| LangItem::RangeToInclusive,
|
||||
) => true,
|
||||
_ => false,
|
||||
};
|
||||
if is_range {
|
||||
if !self.maybe_suggest_range_literal(&mut e, item_def_id, *ident) {
|
||||
let msg = "constants only support matching by type, \
|
||||
if you meant to match against a range of values, \
|
||||
|
||||
@@ -2,9 +2,8 @@ use std::cell::RefCell;
|
||||
use std::ops::Deref;
|
||||
|
||||
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::{HirId, HirIdMap};
|
||||
use rustc_hir::{self as hir, HirId, HirIdMap, LangItem};
|
||||
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode};
|
||||
@@ -137,7 +136,7 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
|
||||
obligation.predicate.kind().skip_binder()
|
||||
&& let Some(ty) =
|
||||
self.shallow_resolve(tpred.self_ty()).ty_vid().map(|t| self.root_var(t))
|
||||
&& self.tcx.lang_items().sized_trait().is_some_and(|st| st != tpred.trait_ref.def_id)
|
||||
&& !self.tcx.is_lang_item(tpred.trait_ref.def_id, LangItem::Sized)
|
||||
{
|
||||
let new_self_ty = self.tcx.types.unit;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{self as hir, LangItem};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_session::lint::FutureIncompatibilityReason;
|
||||
use rustc_session::{declare_lint, impl_lint_pass};
|
||||
@@ -81,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for ShadowedIntoIter {
|
||||
let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) else {
|
||||
return;
|
||||
};
|
||||
if Some(method_def_id) != cx.tcx.lang_items().into_iter_fn() {
|
||||
if !cx.tcx.is_lang_item(method_def_id, LangItem::IntoIterIntoIter) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,11 +35,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
/// returns a corresponding [`ty::ClosureKind`].
|
||||
/// For any other [`DefId`] return `None`.
|
||||
pub fn fn_trait_kind_from_def_id(self, id: DefId) -> Option<ty::ClosureKind> {
|
||||
let items = self.lang_items();
|
||||
match Some(id) {
|
||||
x if x == items.fn_trait() => Some(ty::ClosureKind::Fn),
|
||||
x if x == items.fn_mut_trait() => Some(ty::ClosureKind::FnMut),
|
||||
x if x == items.fn_once_trait() => Some(ty::ClosureKind::FnOnce),
|
||||
match self.as_lang_item(id)? {
|
||||
LangItem::Fn => Some(ty::ClosureKind::Fn),
|
||||
LangItem::FnMut => Some(ty::ClosureKind::FnMut),
|
||||
LangItem::FnOnce => Some(ty::ClosureKind::FnOnce),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -48,11 +47,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
/// returns a corresponding [`ty::ClosureKind`].
|
||||
/// For any other [`DefId`] return `None`.
|
||||
pub fn async_fn_trait_kind_from_def_id(self, id: DefId) -> Option<ty::ClosureKind> {
|
||||
let items = self.lang_items();
|
||||
match Some(id) {
|
||||
x if x == items.async_fn_trait() => Some(ty::ClosureKind::Fn),
|
||||
x if x == items.async_fn_mut_trait() => Some(ty::ClosureKind::FnMut),
|
||||
x if x == items.async_fn_once_trait() => Some(ty::ClosureKind::FnOnce),
|
||||
match self.as_lang_item(id)? {
|
||||
LangItem::AsyncFn => Some(ty::ClosureKind::Fn),
|
||||
LangItem::AsyncFnMut => Some(ty::ClosureKind::FnMut),
|
||||
LangItem::AsyncFnOnce => Some(ty::ClosureKind::FnOnce),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1774,9 +1774,7 @@ impl<'tcx> Ty<'tcx> {
|
||||
match pointee_ty.ptr_metadata_ty_or_tail(tcx, |x| x) {
|
||||
Ok(metadata_ty) => metadata_ty,
|
||||
Err(tail_ty) => {
|
||||
let Some(metadata_def_id) = tcx.lang_items().metadata_type() else {
|
||||
bug!("No metadata_type lang item while looking at {self:?}")
|
||||
};
|
||||
let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None);
|
||||
Ty::new_projection(tcx, metadata_def_id, [tail_ty])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::ops::ControlFlow;
|
||||
use rustc_data_structures::graph::iterate::{
|
||||
NodeStatus, TriColorDepthFirstSearch, TriColorVisitor,
|
||||
};
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_middle::mir::{self, BasicBlock, BasicBlocks, Body, Terminator, TerminatorKind};
|
||||
use rustc_middle::ty::{self, GenericArg, GenericArgs, Instance, Ty, TyCtxt};
|
||||
@@ -44,8 +45,7 @@ impl<'tcx> MirLint<'tcx> for CheckDropRecursion {
|
||||
if let DefKind::AssocFn = tcx.def_kind(def_id)
|
||||
&& let Some(trait_ref) =
|
||||
tcx.impl_of_method(def_id.to_def_id()).and_then(|def_id| tcx.impl_trait_ref(def_id))
|
||||
&& let Some(drop_trait) = tcx.lang_items().drop_trait()
|
||||
&& drop_trait == trait_ref.instantiate_identity().def_id
|
||||
&& tcx.is_lang_item(trait_ref.instantiate_identity().def_id, LangItem::Drop)
|
||||
// avoid erroneous `Drop` impls from causing ICEs below
|
||||
&& let sig = tcx.fn_sig(def_id).instantiate_identity()
|
||||
&& sig.inputs().skip_binder().len() == 1
|
||||
|
||||
@@ -223,7 +223,7 @@ where
|
||||
match mono_item.instantiation_mode(cx.tcx) {
|
||||
InstantiationMode::GloballyShared { .. } => {}
|
||||
InstantiationMode::LocalCopy => {
|
||||
if Some(mono_item.def_id()) != cx.tcx.lang_items().start_fn() {
|
||||
if !cx.tcx.is_lang_item(mono_item.def_id(), LangItem::Start) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,9 +81,7 @@ pub fn call_kind<'tcx>(
|
||||
}
|
||||
});
|
||||
|
||||
let fn_call = parent.and_then(|p| {
|
||||
lang_items::FN_TRAITS.iter().filter_map(|&l| tcx.lang_items().get(l)).find(|&id| id == p)
|
||||
});
|
||||
let fn_call = parent.filter(|&p| tcx.fn_trait_kind_from_def_id(p).is_some());
|
||||
|
||||
let operator = if !from_hir_call && let Some(p) = parent {
|
||||
lang_items::OPERATORS.iter().filter_map(|&l| tcx.lang_items().get(l)).find(|&id| id == p)
|
||||
|
||||
@@ -146,7 +146,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
&& leaf_trait_predicate.def_id() != root_pred.def_id()
|
||||
// The root trait is not `Unsize`, as to avoid talking about it in
|
||||
// `tests/ui/coercion/coerce-issue-49593-box-never.rs`.
|
||||
&& Some(root_pred.def_id()) != self.tcx.lang_items().unsize_trait()
|
||||
&& !self.tcx.is_lang_item(root_pred.def_id(), LangItem::Unsize)
|
||||
{
|
||||
(
|
||||
self.resolve_vars_if_possible(
|
||||
@@ -2274,10 +2274,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
// auto-traits or fundamental traits that might not be exactly what
|
||||
// the user might expect to be presented with. Instead this is
|
||||
// useful for less general traits.
|
||||
if peeled
|
||||
&& !self.tcx.trait_is_auto(def_id)
|
||||
&& !self.tcx.lang_items().iter().any(|(_, id)| id == def_id)
|
||||
{
|
||||
if peeled && !self.tcx.trait_is_auto(def_id) && self.tcx.as_lang_item(def_id).is_none() {
|
||||
let impl_candidates = self.find_similar_impl_candidates(trait_pred);
|
||||
self.report_similar_impl_candidates(
|
||||
&impl_candidates,
|
||||
@@ -3013,8 +3010,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
// This shouldn't be common unless manually implementing one of the
|
||||
// traits manually, but don't make it more confusing when it does
|
||||
// happen.
|
||||
if Some(expected_trait_ref.def_id) != self.tcx.lang_items().coroutine_trait() && not_tupled
|
||||
{
|
||||
if !self.tcx.is_lang_item(expected_trait_ref.def_id, LangItem::Coroutine) && not_tupled {
|
||||
return Ok(self.report_and_explain_type_error(
|
||||
TypeTrace::trait_refs(&obligation.cause, expected_trait_ref, found_trait_ref),
|
||||
obligation.param_env,
|
||||
|
||||
@@ -3844,12 +3844,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
);
|
||||
if let ty::PredicateKind::Clause(clause) = failed_pred.kind().skip_binder()
|
||||
&& let ty::ClauseKind::Trait(pred) = clause
|
||||
&& [
|
||||
tcx.lang_items().fn_once_trait(),
|
||||
tcx.lang_items().fn_mut_trait(),
|
||||
tcx.lang_items().fn_trait(),
|
||||
]
|
||||
.contains(&Some(pred.def_id()))
|
||||
&& tcx.fn_trait_kind_from_def_id(pred.def_id()).is_some()
|
||||
{
|
||||
if let [stmt, ..] = block.stmts
|
||||
&& let hir::StmtKind::Semi(value) = stmt.kind
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause};
|
||||
use rustc_infer::traits::{
|
||||
@@ -452,9 +453,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
|
||||
// We do this as a separate loop so that we do not choose to tell the user about some nested
|
||||
// goal before we encounter a `T: FnPtr` nested goal.
|
||||
for nested_goal in &nested_goals {
|
||||
if let Some(fn_ptr_trait) = tcx.lang_items().fn_ptr_trait()
|
||||
&& let Some(poly_trait_pred) = nested_goal.goal().predicate.as_trait_clause()
|
||||
&& poly_trait_pred.def_id() == fn_ptr_trait
|
||||
if let Some(poly_trait_pred) = nested_goal.goal().predicate.as_trait_clause()
|
||||
&& tcx.is_lang_item(poly_trait_pred.def_id(), LangItem::FnPtrTrait)
|
||||
&& let Err(NoSolution) = nested_goal.result()
|
||||
{
|
||||
return ControlFlow::Break(self.obligation.clone());
|
||||
|
||||
@@ -965,36 +965,38 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
||||
let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
|
||||
|
||||
let tcx = selcx.tcx();
|
||||
let lang_items = selcx.tcx().lang_items();
|
||||
if [
|
||||
lang_items.coroutine_trait(),
|
||||
lang_items.future_trait(),
|
||||
lang_items.iterator_trait(),
|
||||
lang_items.async_iterator_trait(),
|
||||
lang_items.fn_trait(),
|
||||
lang_items.fn_mut_trait(),
|
||||
lang_items.fn_once_trait(),
|
||||
lang_items.async_fn_trait(),
|
||||
lang_items.async_fn_mut_trait(),
|
||||
lang_items.async_fn_once_trait(),
|
||||
]
|
||||
.contains(&Some(trait_ref.def_id))
|
||||
{
|
||||
true
|
||||
} else if tcx.is_lang_item(trait_ref.def_id, LangItem::AsyncFnKindHelper) {
|
||||
// FIXME(async_closures): Validity constraints here could be cleaned up.
|
||||
if obligation.predicate.args.type_at(0).is_ty_var()
|
||||
|| obligation.predicate.args.type_at(4).is_ty_var()
|
||||
|| obligation.predicate.args.type_at(5).is_ty_var()
|
||||
{
|
||||
candidate_set.mark_ambiguous();
|
||||
true
|
||||
} else {
|
||||
obligation.predicate.args.type_at(0).to_opt_closure_kind().is_some()
|
||||
&& obligation.predicate.args.type_at(1).to_opt_closure_kind().is_some()
|
||||
match selcx.tcx().as_lang_item(trait_ref.def_id) {
|
||||
Some(
|
||||
LangItem::Coroutine
|
||||
| LangItem::Future
|
||||
| LangItem::Iterator
|
||||
| LangItem::AsyncIterator
|
||||
| LangItem::Fn
|
||||
| LangItem::FnMut
|
||||
| LangItem::FnOnce
|
||||
| LangItem::AsyncFn
|
||||
| LangItem::AsyncFnMut
|
||||
| LangItem::AsyncFnOnce,
|
||||
) => true,
|
||||
Some(LangItem::AsyncFnKindHelper) => {
|
||||
// FIXME(async_closures): Validity constraints here could be cleaned up.
|
||||
if obligation.predicate.args.type_at(0).is_ty_var()
|
||||
|| obligation.predicate.args.type_at(4).is_ty_var()
|
||||
|| obligation.predicate.args.type_at(5).is_ty_var()
|
||||
{
|
||||
candidate_set.mark_ambiguous();
|
||||
true
|
||||
} else {
|
||||
obligation.predicate.args.type_at(0).to_opt_closure_kind().is_some()
|
||||
&& obligation
|
||||
.predicate
|
||||
.args
|
||||
.type_at(1)
|
||||
.to_opt_closure_kind()
|
||||
.is_some()
|
||||
}
|
||||
}
|
||||
} else if tcx.is_lang_item(trait_ref.def_id, LangItem::DiscriminantKind) {
|
||||
match self_ty.kind() {
|
||||
Some(LangItem::DiscriminantKind) => match self_ty.kind() {
|
||||
ty::Bool
|
||||
| ty::Char
|
||||
| ty::Int(_)
|
||||
@@ -1031,9 +1033,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
||||
| ty::Placeholder(..)
|
||||
| ty::Infer(..)
|
||||
| ty::Error(_) => false,
|
||||
}
|
||||
} else if tcx.is_lang_item(trait_ref.def_id, LangItem::AsyncDestruct) {
|
||||
match self_ty.kind() {
|
||||
},
|
||||
Some(LangItem::AsyncDestruct) => match self_ty.kind() {
|
||||
ty::Bool
|
||||
| ty::Char
|
||||
| ty::Int(_)
|
||||
@@ -1068,101 +1069,104 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
||||
| ty::Placeholder(..)
|
||||
| ty::Infer(_)
|
||||
| ty::Error(_) => false,
|
||||
}
|
||||
} else if tcx.is_lang_item(trait_ref.def_id, LangItem::PointeeTrait) {
|
||||
let tail = selcx.tcx().struct_tail_raw(
|
||||
self_ty,
|
||||
|ty| {
|
||||
// We throw away any obligations we get from this, since we normalize
|
||||
// and confirm these obligations once again during confirmation
|
||||
normalize_with_depth(
|
||||
selcx,
|
||||
obligation.param_env,
|
||||
obligation.cause.clone(),
|
||||
obligation.recursion_depth + 1,
|
||||
ty,
|
||||
)
|
||||
.value
|
||||
},
|
||||
|| {},
|
||||
);
|
||||
},
|
||||
Some(LangItem::PointeeTrait) => {
|
||||
let tail = selcx.tcx().struct_tail_raw(
|
||||
self_ty,
|
||||
|ty| {
|
||||
// We throw away any obligations we get from this, since we normalize
|
||||
// and confirm these obligations once again during confirmation
|
||||
normalize_with_depth(
|
||||
selcx,
|
||||
obligation.param_env,
|
||||
obligation.cause.clone(),
|
||||
obligation.recursion_depth + 1,
|
||||
ty,
|
||||
)
|
||||
.value
|
||||
},
|
||||
|| {},
|
||||
);
|
||||
|
||||
match tail.kind() {
|
||||
ty::Bool
|
||||
| ty::Char
|
||||
| ty::Int(_)
|
||||
| ty::Uint(_)
|
||||
| ty::Float(_)
|
||||
| ty::Str
|
||||
| ty::Array(..)
|
||||
| ty::Pat(..)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(..)
|
||||
| ty::Ref(..)
|
||||
| ty::FnDef(..)
|
||||
| ty::FnPtr(..)
|
||||
| ty::Dynamic(..)
|
||||
| ty::Closure(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
| ty::Coroutine(..)
|
||||
| ty::CoroutineWitness(..)
|
||||
| ty::Never
|
||||
// Extern types have unit metadata, according to RFC 2850
|
||||
| ty::Foreign(_)
|
||||
// If returned by `struct_tail` this is a unit struct
|
||||
// without any fields, or not a struct, and therefore is Sized.
|
||||
| ty::Adt(..)
|
||||
// If returned by `struct_tail` this is the empty tuple.
|
||||
| ty::Tuple(..)
|
||||
// Integers and floats are always Sized, and so have unit type metadata.
|
||||
| ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..))
|
||||
// This happens if we reach the recursion limit when finding the struct tail.
|
||||
| ty::Error(..) => true,
|
||||
match tail.kind() {
|
||||
ty::Bool
|
||||
| ty::Char
|
||||
| ty::Int(_)
|
||||
| ty::Uint(_)
|
||||
| ty::Float(_)
|
||||
| ty::Str
|
||||
| ty::Array(..)
|
||||
| ty::Pat(..)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(..)
|
||||
| ty::Ref(..)
|
||||
| ty::FnDef(..)
|
||||
| ty::FnPtr(..)
|
||||
| ty::Dynamic(..)
|
||||
| ty::Closure(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
| ty::Coroutine(..)
|
||||
| ty::CoroutineWitness(..)
|
||||
| ty::Never
|
||||
// Extern types have unit metadata, according to RFC 2850
|
||||
| ty::Foreign(_)
|
||||
// If returned by `struct_tail` this is a unit struct
|
||||
// without any fields, or not a struct, and therefore is Sized.
|
||||
| ty::Adt(..)
|
||||
// If returned by `struct_tail` this is the empty tuple.
|
||||
| ty::Tuple(..)
|
||||
// Integers and floats are always Sized, and so have unit type metadata.
|
||||
| ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..))
|
||||
// This happens if we reach the recursion limit when finding the struct tail.
|
||||
| ty::Error(..) => true,
|
||||
|
||||
// We normalize from `Wrapper<Tail>::Metadata` to `Tail::Metadata` if able.
|
||||
// Otherwise, type parameters, opaques, and unnormalized projections have
|
||||
// unit metadata if they're known (e.g. by the param_env) to be sized.
|
||||
ty::Param(_) | ty::Alias(..)
|
||||
if self_ty != tail
|
||||
|| selcx.infcx.predicate_must_hold_modulo_regions(
|
||||
&obligation.with(
|
||||
selcx.tcx(),
|
||||
ty::TraitRef::new(
|
||||
// We normalize from `Wrapper<Tail>::Metadata` to `Tail::Metadata` if able.
|
||||
// Otherwise, type parameters, opaques, and unnormalized projections have
|
||||
// unit metadata if they're known (e.g. by the param_env) to be sized.
|
||||
ty::Param(_) | ty::Alias(..)
|
||||
if self_ty != tail
|
||||
|| selcx.infcx.predicate_must_hold_modulo_regions(
|
||||
&obligation.with(
|
||||
selcx.tcx(),
|
||||
selcx.tcx().require_lang_item(
|
||||
LangItem::Sized,
|
||||
Some(obligation.cause.span),
|
||||
ty::TraitRef::new(
|
||||
selcx.tcx(),
|
||||
selcx.tcx().require_lang_item(
|
||||
LangItem::Sized,
|
||||
Some(obligation.cause.span),
|
||||
),
|
||||
[self_ty],
|
||||
),
|
||||
[self_ty],
|
||||
),
|
||||
),
|
||||
) =>
|
||||
{
|
||||
true
|
||||
}
|
||||
|
||||
ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
|
||||
|
||||
// FIXME(compiler-errors): are Bound and Placeholder types ever known sized?
|
||||
ty::Param(_)
|
||||
| ty::Alias(..)
|
||||
| ty::Bound(..)
|
||||
| ty::Placeholder(..)
|
||||
| ty::Infer(..) => {
|
||||
if tail.has_infer_types() {
|
||||
candidate_set.mark_ambiguous();
|
||||
) =>
|
||||
{
|
||||
true
|
||||
}
|
||||
|
||||
ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
|
||||
|
||||
// FIXME(compiler-errors): are Bound and Placeholder types ever known sized?
|
||||
ty::Param(_)
|
||||
| ty::Alias(..)
|
||||
| ty::Bound(..)
|
||||
| ty::Placeholder(..)
|
||||
| ty::Infer(..) => {
|
||||
if tail.has_infer_types() {
|
||||
candidate_set.mark_ambiguous();
|
||||
}
|
||||
false
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
} else if tcx.trait_is_auto(trait_ref.def_id) {
|
||||
tcx.dcx().span_delayed_bug(
|
||||
tcx.def_span(obligation.predicate.def_id),
|
||||
"associated types not allowed on auto traits",
|
||||
);
|
||||
false
|
||||
} else {
|
||||
bug!("unexpected builtin trait with associated type: {trait_ref:?}")
|
||||
_ if tcx.trait_is_auto(trait_ref.def_id) => {
|
||||
tcx.dcx().span_delayed_bug(
|
||||
tcx.def_span(obligation.predicate.def_id),
|
||||
"associated types not allowed on auto traits",
|
||||
);
|
||||
false
|
||||
}
|
||||
_ => {
|
||||
bug!("unexpected builtin trait with associated type: {trait_ref:?}")
|
||||
}
|
||||
}
|
||||
}
|
||||
ImplSource::Param(..) => {
|
||||
|
||||
Reference in New Issue
Block a user