Auto merge of #139845 - Zalathar:rollup-u5u5y1v, r=Zalathar
Rollup of 17 pull requests Successful merges: - #138374 (Enable contracts for const functions) - #138380 (ci: add runners for vanilla LLVM 20) - #138393 (Allow const patterns of matches to contain pattern types) - #139517 (std: sys: process: uefi: Use NULL stdin by default) - #139554 (std: add Output::exit_ok) - #139660 (compiletest: Add an experimental new executor to replace libtest) - #139669 (Overhaul `AssocItem`) - #139671 (Proc macro span API redesign: Replace proc_macro::SourceFile by Span::{file, local_file}) - #139750 (std/thread: Use default stack size from menuconfig for NuttX) - #139772 (Remove `hir::Map`) - #139785 (Let CStrings be either 1 or 2 byte aligned.) - #139789 (do not unnecessarily leak auto traits in item bounds) - #139791 (drop global where-bounds before merging candidates) - #139798 (normalize: prefer `ParamEnv` over `AliasBound` candidates) - #139822 (Fix: Map EOPNOTSUPP to ErrorKind::Unsupported on Unix) - #139833 (Fix some HIR pretty-printing problems) - #139836 (Basic tests of MPMC receiver cloning) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
f433fa46b0
173 changed files with 2499 additions and 994 deletions
|
@ -85,7 +85,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
.delegation_fn_sigs
|
||||
.get(&local_def_id)
|
||||
.is_some_and(|sig| sig.has_self),
|
||||
None => self.tcx.associated_item(def_id).fn_has_self_parameter,
|
||||
None => self.tcx.associated_item(def_id).is_method(),
|
||||
},
|
||||
_ => span_bug!(span, "unexpected DefKind for delegation item"),
|
||||
}
|
||||
|
|
|
@ -399,12 +399,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
&mut self,
|
||||
expr: &'hir hir::Expr<'hir>,
|
||||
span: Span,
|
||||
check_ident: Ident,
|
||||
check_hir_id: HirId,
|
||||
cond_ident: Ident,
|
||||
cond_hir_id: HirId,
|
||||
) -> &'hir hir::Expr<'hir> {
|
||||
let checker_fn = self.expr_ident(span, check_ident, check_hir_id);
|
||||
let span = self.mark_span_with_reason(DesugaringKind::Contract, span, None);
|
||||
self.expr_call(span, checker_fn, std::slice::from_ref(expr))
|
||||
let cond_fn = self.expr_ident(span, cond_ident, cond_hir_id);
|
||||
let call_expr = self.expr_call_lang_item_fn_mut(
|
||||
span,
|
||||
hir::LangItem::ContractCheckEnsures,
|
||||
arena_vec![self; *cond_fn, *expr],
|
||||
);
|
||||
self.arena.alloc(call_expr)
|
||||
}
|
||||
|
||||
pub(crate) fn lower_const_block(&mut self, c: &AnonConst) -> hir::ConstBlock {
|
||||
|
|
|
@ -1206,8 +1206,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let precond = if let Some(req) = &contract.requires {
|
||||
// Lower the precondition check intrinsic.
|
||||
let lowered_req = this.lower_expr_mut(&req);
|
||||
let req_span = this.mark_span_with_reason(
|
||||
DesugaringKind::Contract,
|
||||
lowered_req.span,
|
||||
None,
|
||||
);
|
||||
let precond = this.expr_call_lang_item_fn_mut(
|
||||
req.span,
|
||||
req_span,
|
||||
hir::LangItem::ContractCheckRequires,
|
||||
&*arena_vec![this; lowered_req],
|
||||
);
|
||||
|
@ -1217,6 +1222,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
};
|
||||
let (postcond, body) = if let Some(ens) = &contract.ensures {
|
||||
let ens_span = this.lower_span(ens.span);
|
||||
let ens_span =
|
||||
this.mark_span_with_reason(DesugaringKind::Contract, ens_span, None);
|
||||
// Set up the postcondition `let` statement.
|
||||
let check_ident: Ident =
|
||||
Ident::from_str_and_span("__ensures_checker", ens_span);
|
||||
|
|
|
@ -647,7 +647,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
&& tc.polarity() == ty::PredicatePolarity::Positive
|
||||
&& supertrait_def_ids(tcx, tc.def_id())
|
||||
.flat_map(|trait_did| tcx.associated_items(trait_did).in_definition_order())
|
||||
.any(|item| item.fn_has_self_parameter)
|
||||
.any(|item| item.is_method())
|
||||
})
|
||||
}) {
|
||||
return None;
|
||||
|
|
|
@ -1557,11 +1557,15 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
CastKind::Transmute => {
|
||||
span_mirbug!(
|
||||
self,
|
||||
rvalue,
|
||||
"Unexpected CastKind::Transmute, which is not permitted in Analysis MIR",
|
||||
);
|
||||
let ty_from = op.ty(self.body, tcx);
|
||||
match ty_from.kind() {
|
||||
ty::Pat(base, _) if base == ty => {}
|
||||
_ => span_mirbug!(
|
||||
self,
|
||||
rvalue,
|
||||
"Unexpected CastKind::Transmute {ty_from:?} -> {ty:?}, which is not permitted in Analysis MIR",
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_middle::ty::{AssocKind, GenericArg};
|
||||
use rustc_middle::ty::{AssocTag, GenericArg};
|
||||
use rustc_session::config::EntryFnType;
|
||||
use rustc_span::{DUMMY_SP, Ident};
|
||||
|
||||
|
@ -107,7 +107,7 @@ pub(crate) fn maybe_create_entry_wrapper(
|
|||
.find_by_ident_and_kind(
|
||||
tcx,
|
||||
Ident::from_str("report"),
|
||||
AssocKind::Fn,
|
||||
AssocTag::Fn,
|
||||
termination_trait,
|
||||
)
|
||||
.unwrap();
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use std::ops::{Bound, Range};
|
||||
use std::sync::Arc;
|
||||
|
||||
use ast::token::IdentIsRaw;
|
||||
use pm::bridge::{
|
||||
|
@ -18,7 +17,7 @@ use rustc_parse::parser::Parser;
|
|||
use rustc_parse::{exp, new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal};
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::def_id::CrateNum;
|
||||
use rustc_span::{BytePos, FileName, Pos, SourceFile, Span, Symbol, sym};
|
||||
use rustc_span::{BytePos, FileName, Pos, Span, Symbol, sym};
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
|
||||
use crate::base::ExtCtxt;
|
||||
|
@ -458,7 +457,6 @@ impl<'a, 'b> Rustc<'a, 'b> {
|
|||
impl server::Types for Rustc<'_, '_> {
|
||||
type FreeFunctions = FreeFunctions;
|
||||
type TokenStream = TokenStream;
|
||||
type SourceFile = Arc<SourceFile>;
|
||||
type Span = Span;
|
||||
type Symbol = Symbol;
|
||||
}
|
||||
|
@ -664,28 +662,6 @@ impl server::TokenStream for Rustc<'_, '_> {
|
|||
}
|
||||
}
|
||||
|
||||
impl server::SourceFile for Rustc<'_, '_> {
|
||||
fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool {
|
||||
Arc::ptr_eq(file1, file2)
|
||||
}
|
||||
|
||||
fn path(&mut self, file: &Self::SourceFile) -> String {
|
||||
match &file.name {
|
||||
FileName::Real(name) => name
|
||||
.local_path()
|
||||
.expect("attempting to get a file path in an imported file in `proc_macro::SourceFile::path`")
|
||||
.to_str()
|
||||
.expect("non-UTF8 file path in `proc_macro::SourceFile::path`")
|
||||
.to_string(),
|
||||
_ => file.name.prefer_local().to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_real(&mut self, file: &Self::SourceFile) -> bool {
|
||||
file.is_real_file()
|
||||
}
|
||||
}
|
||||
|
||||
impl server::Span for Rustc<'_, '_> {
|
||||
fn debug(&mut self, span: Self::Span) -> String {
|
||||
if self.ecx.ecfg.span_debug {
|
||||
|
@ -695,8 +671,29 @@ impl server::Span for Rustc<'_, '_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn source_file(&mut self, span: Self::Span) -> Self::SourceFile {
|
||||
self.psess().source_map().lookup_char_pos(span.lo()).file
|
||||
fn file(&mut self, span: Self::Span) -> String {
|
||||
self.psess()
|
||||
.source_map()
|
||||
.lookup_char_pos(span.lo())
|
||||
.file
|
||||
.name
|
||||
.prefer_remapped_unconditionaly()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn local_file(&mut self, span: Self::Span) -> Option<String> {
|
||||
self.psess()
|
||||
.source_map()
|
||||
.lookup_char_pos(span.lo())
|
||||
.file
|
||||
.name
|
||||
.clone()
|
||||
.into_local_path()
|
||||
.map(|p| {
|
||||
p.to_str()
|
||||
.expect("non-UTF8 file path in `proc_macro::SourceFile::path`")
|
||||
.to_string()
|
||||
})
|
||||
}
|
||||
|
||||
fn parent(&mut self, span: Self::Span) -> Option<Self::Span> {
|
||||
|
|
|
@ -25,7 +25,10 @@ fn invocation_relative_path_to_absolute(span: Span, path: &str) -> PathBuf {
|
|||
path.to_path_buf()
|
||||
} else {
|
||||
// `/a/b/c/foo/bar.rs` contains the current macro invocation
|
||||
#[cfg(bootstrap)]
|
||||
let mut source_file_path = span.source_file().path();
|
||||
#[cfg(not(bootstrap))]
|
||||
let mut source_file_path = span.local_file().unwrap();
|
||||
// `/a/b/c/foo/`
|
||||
source_file_path.pop();
|
||||
// `/a/b/c/foo/../locales/en-US/example.ftl`
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
//! 1. **Shallow visit**: Get a simple callback for every item (or item-like thing) in the HIR.
|
||||
//! - Example: find all items with a `#[foo]` attribute on them.
|
||||
//! - How: Use the `hir_crate_items` or `hir_module_items` query to traverse over item-like ids
|
||||
//! (ItemId, TraitItemId, etc.) and use tcx.def_kind and `tcx.hir().item*(id)` to filter and
|
||||
//! (ItemId, TraitItemId, etc.) and use tcx.def_kind and `tcx.hir_item*(id)` to filter and
|
||||
//! access actual item-like thing, respectively.
|
||||
//! - Pro: Efficient; just walks the lists of item ids and gives users control whether to access
|
||||
//! the hir_owners themselves or not.
|
||||
|
|
|
@ -442,6 +442,8 @@ language_item_table! {
|
|||
DefaultTrait3, sym::default_trait3, default_trait3_trait, Target::Trait, GenericRequirement::None;
|
||||
DefaultTrait2, sym::default_trait2, default_trait2_trait, Target::Trait, GenericRequirement::None;
|
||||
DefaultTrait1, sym::default_trait1, default_trait1_trait, Target::Trait, GenericRequirement::None;
|
||||
|
||||
ContractCheckEnsures, sym::contract_check_ensures, contract_check_ensures_fn, Target::Fn, GenericRequirement::None;
|
||||
}
|
||||
|
||||
/// The requirement imposed on the generics of a lang item
|
||||
|
|
|
@ -443,13 +443,13 @@ fn best_definition_site_of_opaque<'tcx>(
|
|||
let impl_def_id = tcx.local_parent(parent);
|
||||
for assoc in tcx.associated_items(impl_def_id).in_definition_order() {
|
||||
match assoc.kind {
|
||||
ty::AssocKind::Const | ty::AssocKind::Fn => {
|
||||
ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => {
|
||||
if let ControlFlow::Break(span) = locator.check(assoc.def_id.expect_local())
|
||||
{
|
||||
return Some(span);
|
||||
}
|
||||
}
|
||||
ty::AssocKind::Type => {}
|
||||
ty::AssocKind::Type { .. } => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -740,7 +740,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
|
||||
for &assoc_item in assoc_items.in_definition_order() {
|
||||
match assoc_item.kind {
|
||||
ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => {
|
||||
ty::AssocKind::Type { .. } if assoc_item.defaultness(tcx).has_value() => {
|
||||
let trait_args = GenericArgs::identity_for_item(tcx, def_id);
|
||||
let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds(
|
||||
tcx,
|
||||
|
@ -942,7 +942,7 @@ fn check_impl_items_against_trait<'tcx>(
|
|||
|
||||
if res.is_ok() {
|
||||
match ty_impl_item.kind {
|
||||
ty::AssocKind::Fn => {
|
||||
ty::AssocKind::Fn { .. } => {
|
||||
compare_impl_item::refine::check_refining_return_position_impl_trait_in_trait(
|
||||
tcx,
|
||||
ty_impl_item,
|
||||
|
@ -952,8 +952,8 @@ fn check_impl_items_against_trait<'tcx>(
|
|||
.instantiate_identity(),
|
||||
);
|
||||
}
|
||||
ty::AssocKind::Const => {}
|
||||
ty::AssocKind::Type => {}
|
||||
ty::AssocKind::Const { .. } => {}
|
||||
ty::AssocKind::Type { .. } => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,9 +43,11 @@ pub(super) fn compare_impl_item(
|
|||
debug!(?impl_trait_ref);
|
||||
|
||||
match impl_item.kind {
|
||||
ty::AssocKind::Fn => compare_impl_method(tcx, impl_item, trait_item, impl_trait_ref),
|
||||
ty::AssocKind::Type => compare_impl_ty(tcx, impl_item, trait_item, impl_trait_ref),
|
||||
ty::AssocKind::Const => compare_impl_const(tcx, impl_item, trait_item, impl_trait_ref),
|
||||
ty::AssocKind::Fn { .. } => compare_impl_method(tcx, impl_item, trait_item, impl_trait_ref),
|
||||
ty::AssocKind::Type { .. } => compare_impl_ty(tcx, impl_item, trait_item, impl_trait_ref),
|
||||
ty::AssocKind::Const { .. } => {
|
||||
compare_impl_const(tcx, impl_item, trait_item, impl_trait_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -651,7 +653,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
|||
cause.span,
|
||||
E0053,
|
||||
"method `{}` has an incompatible return type for trait",
|
||||
trait_m.name
|
||||
trait_m.name()
|
||||
);
|
||||
infcx.err_ctxt().note_type_err(
|
||||
&mut diag,
|
||||
|
@ -1029,11 +1031,11 @@ fn report_trait_method_mismatch<'tcx>(
|
|||
impl_err_span,
|
||||
E0053,
|
||||
"method `{}` has an incompatible type for trait",
|
||||
trait_m.name
|
||||
trait_m.name()
|
||||
);
|
||||
match &terr {
|
||||
TypeError::ArgumentMutability(0) | TypeError::ArgumentSorts(_, 0)
|
||||
if trait_m.fn_has_self_parameter =>
|
||||
if trait_m.is_method() =>
|
||||
{
|
||||
let ty = trait_sig.inputs()[0];
|
||||
let sugg = get_self_string(ty, |ty| ty == impl_trait_ref.self_ty());
|
||||
|
@ -1252,7 +1254,7 @@ fn compare_self_type<'tcx>(
|
|||
get_self_string(self_arg_ty, can_eq_self)
|
||||
};
|
||||
|
||||
match (trait_m.fn_has_self_parameter, impl_m.fn_has_self_parameter) {
|
||||
match (trait_m.is_method(), impl_m.is_method()) {
|
||||
(false, false) | (true, true) => {}
|
||||
|
||||
(false, true) => {
|
||||
|
@ -1263,14 +1265,14 @@ fn compare_self_type<'tcx>(
|
|||
impl_m_span,
|
||||
E0185,
|
||||
"method `{}` has a `{}` declaration in the impl, but not in the trait",
|
||||
trait_m.name,
|
||||
trait_m.name(),
|
||||
self_descr
|
||||
);
|
||||
err.span_label(impl_m_span, format!("`{self_descr}` used in impl"));
|
||||
if let Some(span) = tcx.hir_span_if_local(trait_m.def_id) {
|
||||
err.span_label(span, format!("trait method declared without `{self_descr}`"));
|
||||
} else {
|
||||
err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
|
||||
err.note_trait_signature(trait_m.name(), trait_m.signature(tcx));
|
||||
}
|
||||
return Err(err.emit_unless(delay));
|
||||
}
|
||||
|
@ -1283,14 +1285,14 @@ fn compare_self_type<'tcx>(
|
|||
impl_m_span,
|
||||
E0186,
|
||||
"method `{}` has a `{}` declaration in the trait, but not in the impl",
|
||||
trait_m.name,
|
||||
trait_m.name(),
|
||||
self_descr
|
||||
);
|
||||
err.span_label(impl_m_span, format!("expected `{self_descr}` in impl"));
|
||||
if let Some(span) = tcx.hir_span_if_local(trait_m.def_id) {
|
||||
err.span_label(span, format!("`{self_descr}` used in trait"));
|
||||
} else {
|
||||
err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
|
||||
err.note_trait_signature(trait_m.name(), trait_m.signature(tcx));
|
||||
}
|
||||
|
||||
return Err(err.emit_unless(delay));
|
||||
|
@ -1360,7 +1362,7 @@ fn compare_number_of_generics<'tcx>(
|
|||
let mut err_occurred = None;
|
||||
for (kind, trait_count, impl_count) in matchings {
|
||||
if impl_count != trait_count {
|
||||
let arg_spans = |kind: ty::AssocKind, generics: &hir::Generics<'_>| {
|
||||
let arg_spans = |item: &ty::AssocItem, generics: &hir::Generics<'_>| {
|
||||
let mut spans = generics
|
||||
.params
|
||||
.iter()
|
||||
|
@ -1370,7 +1372,7 @@ fn compare_number_of_generics<'tcx>(
|
|||
} => {
|
||||
// A fn can have an arbitrary number of extra elided lifetimes for the
|
||||
// same signature.
|
||||
!matches!(kind, ty::AssocKind::Fn)
|
||||
!item.is_fn()
|
||||
}
|
||||
_ => true,
|
||||
})
|
||||
|
@ -1383,7 +1385,7 @@ fn compare_number_of_generics<'tcx>(
|
|||
};
|
||||
let (trait_spans, impl_trait_spans) = if let Some(def_id) = trait_.def_id.as_local() {
|
||||
let trait_item = tcx.hir_expect_trait_item(def_id);
|
||||
let arg_spans: Vec<Span> = arg_spans(trait_.kind, trait_item.generics);
|
||||
let arg_spans: Vec<Span> = arg_spans(&trait_, trait_item.generics);
|
||||
let impl_trait_spans: Vec<Span> = trait_item
|
||||
.generics
|
||||
.params
|
||||
|
@ -1409,7 +1411,7 @@ fn compare_number_of_generics<'tcx>(
|
|||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
let spans = arg_spans(impl_.kind, impl_item.generics);
|
||||
let spans = arg_spans(&impl_, impl_item.generics);
|
||||
let span = spans.first().copied();
|
||||
|
||||
let mut err = tcx.dcx().struct_span_err(
|
||||
|
@ -1418,7 +1420,7 @@ fn compare_number_of_generics<'tcx>(
|
|||
"{} `{}` has {} {kind} parameter{} but its trait \
|
||||
declaration has {} {kind} parameter{}",
|
||||
item_kind,
|
||||
trait_.name,
|
||||
trait_.name(),
|
||||
impl_count,
|
||||
pluralize!(impl_count),
|
||||
trait_count,
|
||||
|
@ -1509,7 +1511,7 @@ fn compare_number_of_method_arguments<'tcx>(
|
|||
impl_span,
|
||||
E0050,
|
||||
"method `{}` has {} but the declaration in trait `{}` has {}",
|
||||
trait_m.name,
|
||||
trait_m.name(),
|
||||
potentially_plural_count(impl_number_args, "parameter"),
|
||||
tcx.def_path_str(trait_m.def_id),
|
||||
trait_number_args
|
||||
|
@ -1524,7 +1526,7 @@ fn compare_number_of_method_arguments<'tcx>(
|
|||
),
|
||||
);
|
||||
} else {
|
||||
err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
|
||||
err.note_trait_signature(trait_m.name(), trait_m.signature(tcx));
|
||||
}
|
||||
|
||||
err.span_label(
|
||||
|
@ -1578,7 +1580,7 @@ fn compare_synthetic_generics<'tcx>(
|
|||
impl_span,
|
||||
E0643,
|
||||
"method `{}` has incompatible signature for trait",
|
||||
trait_m.name
|
||||
trait_m.name()
|
||||
);
|
||||
err.span_label(trait_span, "declaration in trait here");
|
||||
if impl_synthetic {
|
||||
|
@ -1700,7 +1702,7 @@ fn compare_generic_param_kinds<'tcx>(
|
|||
trait_item: ty::AssocItem,
|
||||
delay: bool,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
assert_eq!(impl_item.kind, trait_item.kind);
|
||||
assert_eq!(impl_item.as_tag(), trait_item.as_tag());
|
||||
|
||||
let ty_const_params_of = |def_id| {
|
||||
tcx.generics_of(def_id).own_params.iter().filter(|param| {
|
||||
|
@ -1738,7 +1740,7 @@ fn compare_generic_param_kinds<'tcx>(
|
|||
E0053,
|
||||
"{} `{}` has an incompatible generic parameter for trait `{}`",
|
||||
impl_item.descr(),
|
||||
trait_item.name,
|
||||
trait_item.name(),
|
||||
&tcx.def_path_str(tcx.parent(trait_item.def_id))
|
||||
);
|
||||
|
||||
|
@ -1874,7 +1876,7 @@ fn compare_const_predicate_entailment<'tcx>(
|
|||
cause.span,
|
||||
E0326,
|
||||
"implemented const `{}` has an incompatible type for trait",
|
||||
trait_ct.name
|
||||
trait_ct.name()
|
||||
);
|
||||
|
||||
let trait_c_span = trait_ct.def_id.as_local().map(|trait_ct_def_id| {
|
||||
|
@ -2232,16 +2234,19 @@ fn param_env_with_gat_bounds<'tcx>(
|
|||
// of the RPITITs associated with the same body. This is because checking
|
||||
// the item bounds of RPITITs often involves nested RPITITs having to prove
|
||||
// bounds about themselves.
|
||||
let impl_tys_to_install = match impl_ty.opt_rpitit_info {
|
||||
None => vec![impl_ty],
|
||||
Some(
|
||||
ty::ImplTraitInTraitData::Impl { fn_def_id }
|
||||
| ty::ImplTraitInTraitData::Trait { fn_def_id, .. },
|
||||
) => tcx
|
||||
let impl_tys_to_install = match impl_ty.kind {
|
||||
ty::AssocKind::Type {
|
||||
data:
|
||||
ty::AssocTypeData::Rpitit(
|
||||
ty::ImplTraitInTraitData::Impl { fn_def_id }
|
||||
| ty::ImplTraitInTraitData::Trait { fn_def_id, .. },
|
||||
),
|
||||
} => tcx
|
||||
.associated_types_for_impl_traits_in_associated_fn(fn_def_id)
|
||||
.iter()
|
||||
.map(|def_id| tcx.associated_item(*def_id))
|
||||
.collect(),
|
||||
_ => vec![impl_ty],
|
||||
};
|
||||
|
||||
for impl_ty in impl_tys_to_install {
|
||||
|
|
|
@ -217,15 +217,11 @@ pub(crate) fn check_intrinsic_type(
|
|||
};
|
||||
(n_tps, 0, 0, inputs, output, hir::Safety::Unsafe)
|
||||
} else if intrinsic_name == sym::contract_check_ensures {
|
||||
// contract_check_ensures::<'a, Ret, C>(&'a Ret, C)
|
||||
// where C: impl Fn(&'a Ret) -> bool,
|
||||
// contract_check_ensures::<Ret, C>(Ret, C) -> Ret
|
||||
// where C: for<'a> Fn(&'a Ret) -> bool,
|
||||
//
|
||||
// so: two type params, one lifetime param, 0 const params, two inputs, no return
|
||||
|
||||
let p = generics.param_at(0, tcx);
|
||||
let r = ty::Region::new_early_param(tcx, p.to_early_bound_region_data());
|
||||
let ref_ret = Ty::new_imm_ref(tcx, r, param(1));
|
||||
(2, 1, 0, vec![ref_ret, param(2)], tcx.types.unit, hir::Safety::Safe)
|
||||
// so: two type params, 0 lifetime param, 0 const params, two inputs, no return
|
||||
(2, 0, 0, vec![param(0), param(1)], param(1), hir::Safety::Safe)
|
||||
} else {
|
||||
let safety = intrinsic_operation_unsafety(tcx, intrinsic_id);
|
||||
let (n_tps, n_cts, inputs, output) = match intrinsic_name {
|
||||
|
|
|
@ -205,7 +205,7 @@ fn missing_items_err(
|
|||
|
||||
let missing_items_msg = missing_items
|
||||
.clone()
|
||||
.map(|trait_item| trait_item.name.to_string())
|
||||
.map(|trait_item| trait_item.name().to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("`, `");
|
||||
|
||||
|
@ -236,7 +236,7 @@ fn missing_items_err(
|
|||
let code = format!("{padding}{snippet}\n{padding}");
|
||||
if let Some(span) = tcx.hir_span_if_local(trait_item.def_id) {
|
||||
missing_trait_item_label
|
||||
.push(errors::MissingTraitItemLabel { span, item: trait_item.name });
|
||||
.push(errors::MissingTraitItemLabel { span, item: trait_item.name() });
|
||||
missing_trait_item.push(errors::MissingTraitItemSuggestion {
|
||||
span: sugg_sp,
|
||||
code,
|
||||
|
@ -407,14 +407,14 @@ fn fn_sig_suggestion<'tcx>(
|
|||
.enumerate()
|
||||
.map(|(i, ty)| {
|
||||
Some(match ty.kind() {
|
||||
ty::Param(_) if assoc.fn_has_self_parameter && i == 0 => "self".to_string(),
|
||||
ty::Param(_) if assoc.is_method() && i == 0 => "self".to_string(),
|
||||
ty::Ref(reg, ref_ty, mutability) if i == 0 => {
|
||||
let reg = format!("{reg} ");
|
||||
let reg = match ®[..] {
|
||||
"'_ " | " " => "",
|
||||
reg => reg,
|
||||
};
|
||||
if assoc.fn_has_self_parameter {
|
||||
if assoc.is_method() {
|
||||
match ref_ty.kind() {
|
||||
ty::Param(param) if param.name == kw::SelfUpper => {
|
||||
format!("&{}{}self", reg, mutability.prefix_str())
|
||||
|
@ -427,7 +427,7 @@ fn fn_sig_suggestion<'tcx>(
|
|||
}
|
||||
}
|
||||
_ => {
|
||||
if assoc.fn_has_self_parameter && i == 0 {
|
||||
if assoc.is_method() && i == 0 {
|
||||
format!("self: {ty}")
|
||||
} else {
|
||||
format!("_: {ty}")
|
||||
|
@ -489,7 +489,7 @@ fn suggestion_signature<'tcx>(
|
|||
);
|
||||
|
||||
match assoc.kind {
|
||||
ty::AssocKind::Fn => fn_sig_suggestion(
|
||||
ty::AssocKind::Fn { .. } => fn_sig_suggestion(
|
||||
tcx,
|
||||
tcx.liberate_late_bound_regions(
|
||||
assoc.def_id,
|
||||
|
@ -499,14 +499,14 @@ fn suggestion_signature<'tcx>(
|
|||
tcx.predicates_of(assoc.def_id).instantiate_own(tcx, args),
|
||||
assoc,
|
||||
),
|
||||
ty::AssocKind::Type => {
|
||||
ty::AssocKind::Type { .. } => {
|
||||
let (generics, where_clauses) = bounds_from_generic_predicates(
|
||||
tcx,
|
||||
tcx.predicates_of(assoc.def_id).instantiate_own(tcx, args),
|
||||
);
|
||||
format!("type {}{generics} = /* Type */{where_clauses};", assoc.name)
|
||||
format!("type {}{generics} = /* Type */{where_clauses};", assoc.name())
|
||||
}
|
||||
ty::AssocKind::Const => {
|
||||
ty::AssocKind::Const { name } => {
|
||||
let ty = tcx.type_of(assoc.def_id).instantiate_identity();
|
||||
let val = tcx
|
||||
.infer_ctxt()
|
||||
|
@ -514,7 +514,7 @@ fn suggestion_signature<'tcx>(
|
|||
.err_ctxt()
|
||||
.ty_kind_suggestion(tcx.param_env(assoc.def_id), ty)
|
||||
.unwrap_or_else(|| "value".to_string());
|
||||
format!("const {}: {} = {};", assoc.name, ty, val)
|
||||
format!("const {}: {} = {};", name, ty, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -408,7 +408,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {
|
|||
let gat_def_id = gat_item.def_id.expect_local();
|
||||
let gat_item = tcx.associated_item(gat_def_id);
|
||||
// If this item is not an assoc ty, or has no args, then it's not a GAT
|
||||
if gat_item.kind != ty::AssocKind::Type {
|
||||
if !gat_item.is_type() {
|
||||
continue;
|
||||
}
|
||||
let gat_generics = tcx.generics_of(gat_def_id);
|
||||
|
@ -432,7 +432,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {
|
|||
|
||||
let item_required_bounds = match tcx.associated_item(item_def_id).kind {
|
||||
// In our example, this corresponds to `into_iter` method
|
||||
ty::AssocKind::Fn => {
|
||||
ty::AssocKind::Fn { .. } => {
|
||||
// For methods, we check the function signature's return type for any GATs
|
||||
// to constrain. In the `into_iter` case, we see that the return type
|
||||
// `Self::Iter<'a>` is a GAT we want to gather any potential missing bounds from.
|
||||
|
@ -453,7 +453,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {
|
|||
)
|
||||
}
|
||||
// In our example, this corresponds to the `Iter` and `Item` associated types
|
||||
ty::AssocKind::Type => {
|
||||
ty::AssocKind::Type { .. } => {
|
||||
// If our associated item is a GAT with missing bounds, add them to
|
||||
// the param-env here. This allows this GAT to propagate missing bounds
|
||||
// to other GATs.
|
||||
|
@ -474,7 +474,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {
|
|||
gat_generics,
|
||||
)
|
||||
}
|
||||
ty::AssocKind::Const => None,
|
||||
ty::AssocKind::Const { .. } => None,
|
||||
};
|
||||
|
||||
if let Some(item_required_bounds) = item_required_bounds {
|
||||
|
@ -1076,7 +1076,7 @@ fn check_associated_item(
|
|||
};
|
||||
|
||||
match item.kind {
|
||||
ty::AssocKind::Const => {
|
||||
ty::AssocKind::Const { .. } => {
|
||||
let ty = tcx.type_of(item.def_id).instantiate_identity();
|
||||
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
|
||||
wfcx.register_wf_obligation(span, loc, ty.into());
|
||||
|
@ -1089,7 +1089,7 @@ fn check_associated_item(
|
|||
);
|
||||
Ok(())
|
||||
}
|
||||
ty::AssocKind::Fn => {
|
||||
ty::AssocKind::Fn { .. } => {
|
||||
let sig = tcx.fn_sig(item.def_id).instantiate_identity();
|
||||
let hir_sig = sig_if_method.expect("bad signature for method");
|
||||
check_fn_or_method(
|
||||
|
@ -1101,7 +1101,7 @@ fn check_associated_item(
|
|||
);
|
||||
check_method_receiver(wfcx, hir_sig, item, self_ty)
|
||||
}
|
||||
ty::AssocKind::Type => {
|
||||
ty::AssocKind::Type { .. } => {
|
||||
if let ty::AssocItemContainer::Trait = item.container {
|
||||
check_associated_type_bounds(wfcx, item, span)
|
||||
}
|
||||
|
@ -1716,7 +1716,7 @@ fn check_method_receiver<'tcx>(
|
|||
) -> Result<(), ErrorGuaranteed> {
|
||||
let tcx = wfcx.tcx();
|
||||
|
||||
if !method.fn_has_self_parameter {
|
||||
if !method.is_method() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
|
|||
|
||||
for &item1 in impl_items1.in_definition_order() {
|
||||
let collision = impl_items2
|
||||
.filter_by_name_unhygienic(item1.name)
|
||||
.filter_by_name_unhygienic(item1.name())
|
||||
.any(|&item2| self.compare_hygienically(item1, item2));
|
||||
|
||||
if collision {
|
||||
|
@ -64,7 +64,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
|
|||
|
||||
fn compare_hygienically(&self, item1: ty::AssocItem, item2: ty::AssocItem) -> bool {
|
||||
// Symbols and namespace match, compare hygienically.
|
||||
item1.kind.namespace() == item2.kind.namespace()
|
||||
item1.namespace() == item2.namespace()
|
||||
&& item1.ident(self.tcx).normalize_to_macros_2_0()
|
||||
== item2.ident(self.tcx).normalize_to_macros_2_0()
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
|
|||
let mut res = Ok(());
|
||||
for &item1 in impl_items1.in_definition_order() {
|
||||
let collision = impl_items2
|
||||
.filter_by_name_unhygienic(item1.name)
|
||||
.filter_by_name_unhygienic(item1.name())
|
||||
.find(|&&item2| self.compare_hygienically(item1, item2));
|
||||
|
||||
if let Some(item2) = collision {
|
||||
|
@ -230,11 +230,11 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
|
|||
let mut ids = impl_items
|
||||
.in_definition_order()
|
||||
.filter_map(|item| {
|
||||
let entry = connected_region_ids.entry(item.name);
|
||||
let entry = connected_region_ids.entry(item.name());
|
||||
if let IndexEntry::Occupied(e) = &entry {
|
||||
Some(*e.get())
|
||||
} else {
|
||||
idents_to_add.push(item.name);
|
||||
idents_to_add.push(item.name());
|
||||
None
|
||||
}
|
||||
})
|
||||
|
|
|
@ -44,7 +44,7 @@ use rustc_trait_selection::traits::ObligationCtxt;
|
|||
use tracing::{debug, instrument};
|
||||
|
||||
use crate::errors;
|
||||
use crate::hir_ty_lowering::errors::assoc_kind_str;
|
||||
use crate::hir_ty_lowering::errors::assoc_tag_str;
|
||||
use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer, RegionInferReason};
|
||||
|
||||
pub(crate) mod dump;
|
||||
|
@ -450,7 +450,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
|
|||
item_def_id: DefId,
|
||||
item_segment: &rustc_hir::PathSegment<'tcx>,
|
||||
poly_trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
kind: ty::AssocKind,
|
||||
assoc_tag: ty::AssocTag,
|
||||
) -> Result<(DefId, ty::GenericArgsRef<'tcx>), ErrorGuaranteed> {
|
||||
if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
|
||||
let item_args = self.lowerer().lower_generic_args_of_assoc_item(
|
||||
|
@ -525,7 +525,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
|
|||
inferred_sugg,
|
||||
bound,
|
||||
mpart_sugg,
|
||||
what: assoc_kind_str(kind),
|
||||
what: assoc_tag_str(assoc_tag),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1811,7 +1811,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
self.tcx,
|
||||
type_def_id,
|
||||
constraint.ident,
|
||||
ty::AssocKind::Fn,
|
||||
ty::AssocTag::Fn,
|
||||
) {
|
||||
bound_vars.extend(
|
||||
self.tcx
|
||||
|
@ -1843,7 +1843,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
self.tcx,
|
||||
type_def_id,
|
||||
constraint.ident,
|
||||
ty::AssocKind::Type,
|
||||
ty::AssocTag::Type,
|
||||
)
|
||||
.map(|(bound_vars, _)| bound_vars);
|
||||
self.with(scope, |this| {
|
||||
|
@ -1875,13 +1875,13 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
assoc_ident: Ident,
|
||||
assoc_kind: ty::AssocKind,
|
||||
assoc_tag: ty::AssocTag,
|
||||
) -> Option<(Vec<ty::BoundVariableKind>, &'tcx ty::AssocItem)> {
|
||||
let trait_defines_associated_item_named = |trait_def_id: DefId| {
|
||||
tcx.associated_items(trait_def_id).find_by_ident_and_kind(
|
||||
tcx,
|
||||
assoc_ident,
|
||||
assoc_kind,
|
||||
assoc_tag,
|
||||
trait_def_id,
|
||||
)
|
||||
};
|
||||
|
@ -1894,8 +1894,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
let Some((def_id, bound_vars)) = stack.pop() else {
|
||||
break None;
|
||||
};
|
||||
// See issue #83753. If someone writes an associated type on a non-trait, just treat it as
|
||||
// there being no supertrait HRTBs.
|
||||
// See issue #83753. If someone writes an associated type on a non-trait, just treat it
|
||||
// as there being no supertrait HRTBs.
|
||||
match tcx.def_kind(def_id) {
|
||||
DefKind::Trait | DefKind::TraitAlias | DefKind::Impl { .. } => {}
|
||||
_ => break None,
|
||||
|
@ -2067,7 +2067,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
self.tcx,
|
||||
trait_def_id,
|
||||
item_segment.ident,
|
||||
ty::AssocKind::Fn,
|
||||
ty::AssocTag::Fn,
|
||||
)
|
||||
});
|
||||
|
||||
|
@ -2112,7 +2112,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
self.tcx,
|
||||
trait_def_id,
|
||||
item_segment.ident,
|
||||
ty::AssocKind::Fn,
|
||||
ty::AssocTag::Fn,
|
||||
) else {
|
||||
return;
|
||||
};
|
||||
|
|
|
@ -32,9 +32,11 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
|
|||
for &assoc_id in tcx.associated_item_def_ids(impl_def_id) {
|
||||
let assoc = tcx.associated_item(assoc_id);
|
||||
match assoc.kind {
|
||||
ty::AssocKind::Const | ty::AssocKind::Fn => locator.check(assoc_id.expect_local()),
|
||||
ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => {
|
||||
locator.check(assoc_id.expect_local())
|
||||
}
|
||||
// Associated types don't have bodies, so they can't constrain hidden types
|
||||
ty::AssocKind::Type => {}
|
||||
ty::AssocKind::Type { .. } => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use GenericArgsInfo::*;
|
|||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{Applicability, Diag, Diagnostic, EmissionGuarantee, MultiSpan, pluralize};
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::ty::{self as ty, AssocItems, AssocKind, TyCtxt};
|
||||
use rustc_middle::ty::{self as ty, AssocItems, TyCtxt};
|
||||
use rustc_span::def_id::DefId;
|
||||
use tracing::debug;
|
||||
|
||||
|
@ -486,13 +486,13 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
|||
let items: &AssocItems = self.tcx.associated_items(self.def_id);
|
||||
items
|
||||
.in_definition_order()
|
||||
.filter(|item| item.kind == AssocKind::Type)
|
||||
.filter(|item| item.is_type())
|
||||
.filter(|item| {
|
||||
!self
|
||||
.gen_args
|
||||
.constraints
|
||||
.iter()
|
||||
.any(|constraint| constraint.ident.name == item.name)
|
||||
.any(|constraint| constraint.ident.name == item.name())
|
||||
})
|
||||
.filter(|item| !item.is_impl_trait_in_trait())
|
||||
.map(|item| self.tcx.item_ident(item.def_id).to_string())
|
||||
|
|
|
@ -431,16 +431,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
) -> Result<(), ErrorGuaranteed> {
|
||||
let tcx = self.tcx();
|
||||
|
||||
let assoc_kind = if constraint.gen_args.parenthesized
|
||||
let assoc_tag = if constraint.gen_args.parenthesized
|
||||
== hir::GenericArgsParentheses::ReturnTypeNotation
|
||||
{
|
||||
ty::AssocKind::Fn
|
||||
ty::AssocTag::Fn
|
||||
} else if let hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(_) } =
|
||||
constraint.kind
|
||||
{
|
||||
ty::AssocKind::Const
|
||||
ty::AssocTag::Const
|
||||
} else {
|
||||
ty::AssocKind::Type
|
||||
ty::AssocTag::Type
|
||||
};
|
||||
|
||||
// Given something like `U: Trait<T = X>`, we want to produce a predicate like
|
||||
|
@ -453,7 +453,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
// trait SuperTrait<A> { type T; }
|
||||
let candidate = if self.probe_trait_that_defines_assoc_item(
|
||||
trait_ref.def_id(),
|
||||
assoc_kind,
|
||||
assoc_tag,
|
||||
constraint.ident,
|
||||
) {
|
||||
// Simple case: The assoc item is defined in the current trait.
|
||||
|
@ -464,7 +464,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
self.probe_single_bound_for_assoc_item(
|
||||
|| traits::supertraits(tcx, trait_ref),
|
||||
AssocItemQSelf::Trait(trait_ref.def_id()),
|
||||
assoc_kind,
|
||||
assoc_tag,
|
||||
constraint.ident,
|
||||
path_span,
|
||||
Some(constraint),
|
||||
|
@ -474,7 +474,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let assoc_item = self
|
||||
.probe_assoc_item(
|
||||
constraint.ident,
|
||||
assoc_kind,
|
||||
assoc_tag,
|
||||
hir_ref_id,
|
||||
constraint.span,
|
||||
candidate.def_id(),
|
||||
|
@ -493,7 +493,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
})
|
||||
.or_insert(constraint.span);
|
||||
|
||||
let projection_term = if let ty::AssocKind::Fn = assoc_kind {
|
||||
let projection_term = if let ty::AssocTag::Fn = assoc_tag {
|
||||
let bound_vars = tcx.late_bound_vars(constraint.hir_id);
|
||||
ty::Binder::bind_with_vars(
|
||||
self.lower_return_type_notation_ty(candidate, assoc_item.def_id, path_span)?.into(),
|
||||
|
@ -542,7 +542,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
};
|
||||
|
||||
match constraint.kind {
|
||||
hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocKind::Fn = assoc_kind => {
|
||||
hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocTag::Fn = assoc_tag => {
|
||||
return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationEqualityBound {
|
||||
span: constraint.span,
|
||||
}));
|
||||
|
@ -679,7 +679,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
trait_def_id,
|
||||
hir_ty.span,
|
||||
item_segment,
|
||||
ty::AssocKind::Type,
|
||||
ty::AssocTag::Type,
|
||||
);
|
||||
return Ty::new_error(tcx, guar);
|
||||
};
|
||||
|
@ -771,7 +771,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
)
|
||||
},
|
||||
AssocItemQSelf::SelfTyAlias,
|
||||
ty::AssocKind::Fn,
|
||||
ty::AssocTag::Fn,
|
||||
assoc_ident,
|
||||
span,
|
||||
None,
|
||||
|
@ -783,7 +783,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
) => self.probe_single_ty_param_bound_for_assoc_item(
|
||||
param_did.expect_local(),
|
||||
qself.span,
|
||||
ty::AssocKind::Fn,
|
||||
ty::AssocTag::Fn,
|
||||
assoc_ident,
|
||||
span,
|
||||
)?,
|
||||
|
@ -823,7 +823,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
|
||||
let trait_def_id = bound.def_id();
|
||||
let assoc_ty = self
|
||||
.probe_assoc_item(assoc_ident, ty::AssocKind::Fn, qpath_hir_id, span, trait_def_id)
|
||||
.probe_assoc_item(assoc_ident, ty::AssocTag::Fn, qpath_hir_id, span, trait_def_id)
|
||||
.expect("failed to find associated type");
|
||||
|
||||
Ok((bound, assoc_ty.def_id))
|
||||
|
|
|
@ -201,7 +201,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
tcx.associated_items(pred.trait_ref.def_id)
|
||||
.in_definition_order()
|
||||
// We only care about associated types.
|
||||
.filter(|item| item.kind == ty::AssocKind::Type)
|
||||
.filter(|item| item.is_type())
|
||||
// No RPITITs -- they're not dyn-compatible for now.
|
||||
.filter(|item| !item.is_impl_trait_in_trait())
|
||||
// If the associated type has a `where Self: Sized` bound,
|
||||
|
|
|
@ -116,7 +116,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
&self,
|
||||
all_candidates: impl Fn() -> I,
|
||||
qself: AssocItemQSelf,
|
||||
assoc_kind: ty::AssocKind,
|
||||
assoc_tag: ty::AssocTag,
|
||||
assoc_ident: Ident,
|
||||
span: Span,
|
||||
constraint: Option<&hir::AssocItemConstraint<'tcx>>,
|
||||
|
@ -134,14 +134,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
}) {
|
||||
return self.complain_about_assoc_kind_mismatch(
|
||||
assoc_item,
|
||||
assoc_kind,
|
||||
assoc_tag,
|
||||
assoc_ident,
|
||||
span,
|
||||
constraint,
|
||||
);
|
||||
}
|
||||
|
||||
let assoc_kind_str = assoc_kind_str(assoc_kind);
|
||||
let assoc_kind_str = assoc_tag_str(assoc_tag);
|
||||
let qself_str = qself.to_string(tcx);
|
||||
|
||||
// The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a
|
||||
|
@ -168,7 +168,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let all_candidate_names: Vec<_> = all_candidates()
|
||||
.flat_map(|r| tcx.associated_items(r.def_id()).in_definition_order())
|
||||
.filter_map(|item| {
|
||||
(!item.is_impl_trait_in_trait() && item.kind == assoc_kind).then_some(item.name)
|
||||
if !item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag {
|
||||
item.opt_name()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -200,7 +204,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
.iter()
|
||||
.flat_map(|trait_def_id| tcx.associated_items(*trait_def_id).in_definition_order())
|
||||
.filter_map(|item| {
|
||||
(!item.is_impl_trait_in_trait() && item.kind == assoc_kind).then_some(item.name)
|
||||
(!item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag)
|
||||
.then_some(item.name())
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -213,7 +218,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
.filter(|trait_def_id| {
|
||||
tcx.associated_items(trait_def_id)
|
||||
.filter_by_name_unhygienic(suggested_name)
|
||||
.any(|item| item.kind == assoc_kind)
|
||||
.any(|item| item.as_tag() == assoc_tag)
|
||||
})
|
||||
.collect::<Vec<_>>()[..]
|
||||
{
|
||||
|
@ -330,14 +335,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
fn complain_about_assoc_kind_mismatch(
|
||||
&self,
|
||||
assoc_item: &ty::AssocItem,
|
||||
assoc_kind: ty::AssocKind,
|
||||
assoc_tag: ty::AssocTag,
|
||||
ident: Ident,
|
||||
span: Span,
|
||||
constraint: Option<&hir::AssocItemConstraint<'tcx>>,
|
||||
) -> ErrorGuaranteed {
|
||||
let tcx = self.tcx();
|
||||
|
||||
let bound_on_assoc_const_label = if let ty::AssocKind::Const = assoc_item.kind
|
||||
let bound_on_assoc_const_label = if let ty::AssocKind::Const { .. } = assoc_item.kind
|
||||
&& let Some(constraint) = constraint
|
||||
&& let hir::AssocItemConstraintKind::Bound { .. } = constraint.kind
|
||||
{
|
||||
|
@ -375,17 +380,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
hir::Term::Ty(ty) => ty.span,
|
||||
hir::Term::Const(ct) => ct.span(),
|
||||
};
|
||||
(span, Some(ident.span), assoc_item.kind, assoc_kind)
|
||||
(span, Some(ident.span), assoc_item.as_tag(), assoc_tag)
|
||||
} else {
|
||||
(ident.span, None, assoc_kind, assoc_item.kind)
|
||||
(ident.span, None, assoc_tag, assoc_item.as_tag())
|
||||
};
|
||||
|
||||
self.dcx().emit_err(errors::AssocKindMismatch {
|
||||
span,
|
||||
expected: assoc_kind_str(expected),
|
||||
got: assoc_kind_str(got),
|
||||
expected: assoc_tag_str(expected),
|
||||
got: assoc_tag_str(got),
|
||||
expected_because_label,
|
||||
assoc_kind: assoc_kind_str(assoc_item.kind),
|
||||
assoc_kind: assoc_tag_str(assoc_item.as_tag()),
|
||||
def_span: tcx.def_span(assoc_item.def_id),
|
||||
bound_on_assoc_const_label,
|
||||
wrap_in_braces_sugg,
|
||||
|
@ -398,9 +403,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
types: &[String],
|
||||
traits: &[String],
|
||||
name: Symbol,
|
||||
kind: ty::AssocKind,
|
||||
assoc_tag: ty::AssocTag,
|
||||
) -> ErrorGuaranteed {
|
||||
let kind_str = assoc_kind_str(kind);
|
||||
let kind_str = assoc_tag_str(assoc_tag);
|
||||
let mut err =
|
||||
struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated {kind_str}");
|
||||
if self
|
||||
|
@ -569,7 +574,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
candidates: Vec<(DefId, (DefId, DefId))>,
|
||||
fulfillment_errors: Vec<FulfillmentError<'tcx>>,
|
||||
span: Span,
|
||||
kind: ty::AssocKind,
|
||||
assoc_tag: ty::AssocTag,
|
||||
) -> ErrorGuaranteed {
|
||||
// FIXME(fmease): This was copied in parts from an old version of `rustc_hir_typeck::method::suggest`.
|
||||
// Either
|
||||
|
@ -579,14 +584,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
|
||||
let tcx = self.tcx();
|
||||
|
||||
let kind_str = assoc_kind_str(kind);
|
||||
let assoc_tag_str = assoc_tag_str(assoc_tag);
|
||||
let adt_did = self_ty.ty_adt_def().map(|def| def.did());
|
||||
let add_def_label = |err: &mut Diag<'_>| {
|
||||
if let Some(did) = adt_did {
|
||||
err.span_label(
|
||||
tcx.def_span(did),
|
||||
format!(
|
||||
"associated {kind_str} `{name}` not found for this {}",
|
||||
"associated {assoc_tag_str} `{name}` not found for this {}",
|
||||
tcx.def_descr(did)
|
||||
),
|
||||
);
|
||||
|
@ -615,11 +620,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
self.dcx(),
|
||||
name.span,
|
||||
E0220,
|
||||
"associated {kind_str} `{name}` not found for `{self_ty}` in the current scope"
|
||||
"associated {assoc_tag_str} `{name}` not found for `{self_ty}` in the current scope"
|
||||
);
|
||||
err.span_label(name.span, format!("associated item not found in `{self_ty}`"));
|
||||
err.note(format!(
|
||||
"the associated {kind_str} was found for\n{type_candidates}{additional_types}",
|
||||
"the associated {assoc_tag_str} was found for\n{type_candidates}{additional_types}",
|
||||
));
|
||||
add_def_label(&mut err);
|
||||
return err.emit();
|
||||
|
@ -700,7 +705,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
|
||||
let mut err = self.dcx().struct_span_err(
|
||||
name.span,
|
||||
format!("the associated {kind_str} `{name}` exists for `{self_ty}`, but its trait bounds were not satisfied")
|
||||
format!("the associated {assoc_tag_str} `{name}` exists for `{self_ty}`, but its trait bounds were not satisfied")
|
||||
);
|
||||
if !bounds.is_empty() {
|
||||
err.note(format!(
|
||||
|
@ -710,7 +715,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
}
|
||||
err.span_label(
|
||||
name.span,
|
||||
format!("associated {kind_str} cannot be referenced on `{self_ty}` due to unsatisfied trait bounds")
|
||||
format!("associated {assoc_tag_str} cannot be referenced on `{self_ty}` due to unsatisfied trait bounds")
|
||||
);
|
||||
|
||||
for (span, mut bounds) in bound_spans {
|
||||
|
@ -761,7 +766,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
// `issue-22560.rs`.
|
||||
let mut dyn_compatibility_violations = Ok(());
|
||||
for (assoc_item, trait_ref) in &missing_assoc_types {
|
||||
names.entry(trait_ref).or_default().push(assoc_item.name);
|
||||
names.entry(trait_ref).or_default().push(assoc_item.name());
|
||||
names_len += 1;
|
||||
|
||||
let violations =
|
||||
|
@ -812,7 +817,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let assoc_item = tcx.associated_items(trait_def).find_by_ident_and_kind(
|
||||
tcx,
|
||||
ident,
|
||||
ty::AssocKind::Type,
|
||||
ty::AssocTag::Type,
|
||||
trait_def,
|
||||
);
|
||||
|
||||
|
@ -852,16 +857,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let mut names: UnordMap<_, usize> = Default::default();
|
||||
for (item, _) in &missing_assoc_types {
|
||||
types_count += 1;
|
||||
*names.entry(item.name).or_insert(0) += 1;
|
||||
*names.entry(item.name()).or_insert(0) += 1;
|
||||
}
|
||||
let mut dupes = false;
|
||||
let mut shadows = false;
|
||||
for (item, trait_ref) in &missing_assoc_types {
|
||||
let prefix = if names[&item.name] > 1 {
|
||||
let name = item.name();
|
||||
let prefix = if names[&name] > 1 {
|
||||
let trait_def_id = trait_ref.def_id();
|
||||
dupes = true;
|
||||
format!("{}::", tcx.def_path_str(trait_def_id))
|
||||
} else if bound_names.get(&item.name).is_some_and(|x| *x != item) {
|
||||
} else if bound_names.get(&name).is_some_and(|x| *x != item) {
|
||||
let trait_def_id = trait_ref.def_id();
|
||||
shadows = true;
|
||||
format!("{}::", tcx.def_path_str(trait_def_id))
|
||||
|
@ -871,7 +877,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
|
||||
let mut is_shadowed = false;
|
||||
|
||||
if let Some(assoc_item) = bound_names.get(&item.name)
|
||||
if let Some(assoc_item) = bound_names.get(&name)
|
||||
&& *assoc_item != item
|
||||
{
|
||||
is_shadowed = true;
|
||||
|
@ -880,17 +886,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
if assoc_item.def_id.is_local() { ", consider renaming it" } else { "" };
|
||||
err.span_label(
|
||||
tcx.def_span(assoc_item.def_id),
|
||||
format!("`{}{}` shadowed here{}", prefix, item.name, rename_message),
|
||||
format!("`{}{}` shadowed here{}", prefix, name, rename_message),
|
||||
);
|
||||
}
|
||||
|
||||
let rename_message = if is_shadowed { ", consider renaming it" } else { "" };
|
||||
|
||||
if let Some(sp) = tcx.hir_span_if_local(item.def_id) {
|
||||
err.span_label(
|
||||
sp,
|
||||
format!("`{}{}` defined here{}", prefix, item.name, rename_message),
|
||||
);
|
||||
err.span_label(sp, format!("`{}{}` defined here{}", prefix, name, rename_message));
|
||||
}
|
||||
}
|
||||
if potential_assoc_types.len() == missing_assoc_types.len() {
|
||||
|
@ -903,7 +906,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
{
|
||||
let types: Vec<_> = missing_assoc_types
|
||||
.iter()
|
||||
.map(|(item, _)| format!("{} = Type", item.name))
|
||||
.map(|(item, _)| format!("{} = Type", item.name()))
|
||||
.collect();
|
||||
let code = if let Some(snippet) = snippet.strip_suffix('>') {
|
||||
// The user wrote `Trait<'a>` or similar and we don't have a type we can
|
||||
|
@ -938,16 +941,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let mut names: FxIndexMap<_, usize> = FxIndexMap::default();
|
||||
for (item, _) in &missing_assoc_types {
|
||||
types_count += 1;
|
||||
*names.entry(item.name).or_insert(0) += 1;
|
||||
*names.entry(item.name()).or_insert(0) += 1;
|
||||
}
|
||||
let mut label = vec![];
|
||||
for (item, trait_ref) in &missing_assoc_types {
|
||||
let postfix = if names[&item.name] > 1 {
|
||||
let name = item.name();
|
||||
let postfix = if names[&name] > 1 {
|
||||
format!(" (from trait `{}`)", trait_ref.print_trait_sugared())
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
label.push(format!("`{}`{}", item.name, postfix));
|
||||
label.push(format!("`{}`{}", name, postfix));
|
||||
}
|
||||
if !label.is_empty() {
|
||||
err.span_label(
|
||||
|
@ -1022,12 +1026,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
.map(|simple_ty| tcx.incoherent_impls(simple_ty))
|
||||
})
|
||||
&& let name = Symbol::intern(&format!("{ident2}_{ident3}"))
|
||||
&& let Some(ty::AssocItem { kind: ty::AssocKind::Fn, .. }) = inherent_impls
|
||||
&& let Some(item) = inherent_impls
|
||||
.iter()
|
||||
.flat_map(|inherent_impl| {
|
||||
tcx.associated_items(inherent_impl).filter_by_name_unhygienic(name)
|
||||
})
|
||||
.next()
|
||||
&& item.is_fn()
|
||||
{
|
||||
Err(struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated type")
|
||||
.with_span_suggestion_verbose(
|
||||
|
@ -1629,10 +1634,10 @@ fn generics_args_err_extend<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn assoc_kind_str(kind: ty::AssocKind) -> &'static str {
|
||||
match kind {
|
||||
ty::AssocKind::Fn => "function",
|
||||
ty::AssocKind::Const => "constant",
|
||||
ty::AssocKind::Type => "type",
|
||||
pub(crate) fn assoc_tag_str(assoc_tag: ty::AssocTag) -> &'static str {
|
||||
match assoc_tag {
|
||||
ty::AssocTag::Fn => "function",
|
||||
ty::AssocTag::Const => "constant",
|
||||
ty::AssocTag::Type => "type",
|
||||
}
|
||||
}
|
||||
|
|
|
@ -501,8 +501,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let names: Vec<_> = tcx
|
||||
.associated_items(trait_def_id)
|
||||
.in_definition_order()
|
||||
.filter(|assoc| assoc.kind.namespace() == Namespace::ValueNS)
|
||||
.map(|cand| cand.name)
|
||||
.filter(|assoc| assoc.namespace() == Namespace::ValueNS)
|
||||
.map(|cand| cand.name())
|
||||
.collect();
|
||||
if let Some(typo) = find_best_match_for_name(&names, segment.ident.name, None) {
|
||||
diag.span_suggestion_verbose(
|
||||
|
|
|
@ -38,8 +38,8 @@ use rustc_middle::middle::stability::AllowUnstable;
|
|||
use rustc_middle::mir::interpret::LitToConstInput;
|
||||
use rustc_middle::ty::print::PrintPolyTraitRefExt as _;
|
||||
use rustc_middle::ty::{
|
||||
self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt,
|
||||
TypeVisitableExt, TypingMode, Upcast, fold_regions,
|
||||
self, AssocTag, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty,
|
||||
TyCtxt, TypeVisitableExt, TypingMode, Upcast, fold_regions,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
|
||||
|
@ -51,7 +51,7 @@ use rustc_trait_selection::traits::wf::object_region_bounds;
|
|||
use rustc_trait_selection::traits::{self, ObligationCtxt};
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use self::errors::assoc_kind_str;
|
||||
use self::errors::assoc_tag_str;
|
||||
use crate::check::check_abi_fn_ptr;
|
||||
use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, NoVariantNamed};
|
||||
use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint};
|
||||
|
@ -168,7 +168,7 @@ pub trait HirTyLowerer<'tcx> {
|
|||
item_def_id: DefId,
|
||||
item_segment: &hir::PathSegment<'tcx>,
|
||||
poly_trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
kind: ty::AssocKind,
|
||||
assoc_tag: ty::AssocTag,
|
||||
) -> Result<(DefId, GenericArgsRef<'tcx>), ErrorGuaranteed>;
|
||||
|
||||
fn lower_fn_sig(
|
||||
|
@ -251,10 +251,10 @@ enum LowerAssocMode {
|
|||
}
|
||||
|
||||
impl LowerAssocMode {
|
||||
fn kind(self) -> ty::AssocKind {
|
||||
fn assoc_tag(self) -> ty::AssocTag {
|
||||
match self {
|
||||
LowerAssocMode::Type { .. } => ty::AssocKind::Type,
|
||||
LowerAssocMode::Const => ty::AssocKind::Const,
|
||||
LowerAssocMode::Type { .. } => ty::AssocTag::Type,
|
||||
LowerAssocMode::Const => ty::AssocTag::Const,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,7 +268,8 @@ impl LowerAssocMode {
|
|||
fn permit_variants(self) -> bool {
|
||||
match self {
|
||||
LowerAssocMode::Type { permit_variants } => permit_variants,
|
||||
// FIXME(mgca): Support paths like `Option::<T>::None` or `Option::<T>::Some` which resolve to const ctors/fn items respectively
|
||||
// FIXME(mgca): Support paths like `Option::<T>::None` or `Option::<T>::Some` which
|
||||
// resolve to const ctors/fn items respectively.
|
||||
LowerAssocMode::Const => false,
|
||||
}
|
||||
}
|
||||
|
@ -932,12 +933,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
fn probe_trait_that_defines_assoc_item(
|
||||
&self,
|
||||
trait_def_id: DefId,
|
||||
assoc_kind: ty::AssocKind,
|
||||
assoc_tag: AssocTag,
|
||||
assoc_ident: Ident,
|
||||
) -> bool {
|
||||
self.tcx()
|
||||
.associated_items(trait_def_id)
|
||||
.find_by_ident_and_kind(self.tcx(), assoc_ident, assoc_kind, trait_def_id)
|
||||
.find_by_ident_and_kind(self.tcx(), assoc_ident, assoc_tag, trait_def_id)
|
||||
.is_some()
|
||||
}
|
||||
|
||||
|
@ -975,7 +976,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
&self,
|
||||
ty_param_def_id: LocalDefId,
|
||||
ty_param_span: Span,
|
||||
kind: ty::AssocKind,
|
||||
assoc_tag: AssocTag,
|
||||
assoc_ident: Ident,
|
||||
span: Span,
|
||||
) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> {
|
||||
|
@ -993,7 +994,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
traits::transitive_bounds_that_define_assoc_item(tcx, trait_refs, assoc_ident)
|
||||
},
|
||||
AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span),
|
||||
kind,
|
||||
assoc_tag,
|
||||
assoc_ident,
|
||||
span,
|
||||
None,
|
||||
|
@ -1010,7 +1011,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
&self,
|
||||
all_candidates: impl Fn() -> I,
|
||||
qself: AssocItemQSelf,
|
||||
assoc_kind: ty::AssocKind,
|
||||
assoc_tag: AssocTag,
|
||||
assoc_ident: Ident,
|
||||
span: Span,
|
||||
constraint: Option<&hir::AssocItemConstraint<'tcx>>,
|
||||
|
@ -1021,14 +1022,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let tcx = self.tcx();
|
||||
|
||||
let mut matching_candidates = all_candidates().filter(|r| {
|
||||
self.probe_trait_that_defines_assoc_item(r.def_id(), assoc_kind, assoc_ident)
|
||||
self.probe_trait_that_defines_assoc_item(r.def_id(), assoc_tag, assoc_ident)
|
||||
});
|
||||
|
||||
let Some(bound) = matching_candidates.next() else {
|
||||
let reported = self.complain_about_assoc_item_not_found(
|
||||
all_candidates,
|
||||
qself,
|
||||
assoc_kind,
|
||||
assoc_tag,
|
||||
assoc_ident,
|
||||
span,
|
||||
constraint,
|
||||
|
@ -1040,7 +1041,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
if let Some(bound2) = matching_candidates.next() {
|
||||
debug!(?bound2);
|
||||
|
||||
let assoc_kind_str = errors::assoc_kind_str(assoc_kind);
|
||||
let assoc_kind_str = errors::assoc_tag_str(assoc_tag);
|
||||
let qself_str = qself.to_string(tcx);
|
||||
let mut err = self.dcx().create_err(crate::errors::AmbiguousAssocItem {
|
||||
span,
|
||||
|
@ -1059,14 +1060,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
},
|
||||
);
|
||||
|
||||
// FIXME(#97583): Print associated item bindings properly (i.e., not as equality predicates!).
|
||||
// FIXME(#97583): Print associated item bindings properly (i.e., not as equality
|
||||
// predicates!).
|
||||
// FIXME: Turn this into a structured, translateable & more actionable suggestion.
|
||||
let mut where_bounds = vec![];
|
||||
for bound in [bound, bound2].into_iter().chain(matching_candidates) {
|
||||
let bound_id = bound.def_id();
|
||||
let bound_span = tcx
|
||||
.associated_items(bound_id)
|
||||
.find_by_ident_and_kind(tcx, assoc_ident, assoc_kind, bound_id)
|
||||
.find_by_ident_and_kind(tcx, assoc_ident, assoc_tag, bound_id)
|
||||
.and_then(|item| tcx.hir_span_if_local(item.def_id));
|
||||
|
||||
if let Some(bound_span) = bound_span {
|
||||
|
@ -1265,7 +1267,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
qself_ty,
|
||||
hir_ref_id,
|
||||
span,
|
||||
mode.kind(),
|
||||
mode.assoc_tag(),
|
||||
)? {
|
||||
return Ok(LoweredAssoc::Term(did, args));
|
||||
}
|
||||
|
@ -1296,7 +1298,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
)
|
||||
},
|
||||
AssocItemQSelf::SelfTyAlias,
|
||||
mode.kind(),
|
||||
mode.assoc_tag(),
|
||||
assoc_ident,
|
||||
span,
|
||||
None,
|
||||
|
@ -1308,12 +1310,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
) => self.probe_single_ty_param_bound_for_assoc_item(
|
||||
param_did.expect_local(),
|
||||
qself.span,
|
||||
mode.kind(),
|
||||
mode.assoc_tag(),
|
||||
assoc_ident,
|
||||
span,
|
||||
)?,
|
||||
_ => {
|
||||
let kind_str = assoc_kind_str(mode.kind());
|
||||
let kind_str = assoc_tag_str(mode.assoc_tag());
|
||||
let reported = if variant_resolution.is_some() {
|
||||
// Variant in type position
|
||||
let msg = format!("expected {kind_str}, found variant `{assoc_ident}`");
|
||||
|
@ -1420,7 +1422,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
&[qself_ty.to_string()],
|
||||
&traits,
|
||||
assoc_ident.name,
|
||||
mode.kind(),
|
||||
mode.assoc_tag(),
|
||||
)
|
||||
};
|
||||
return Err(reported);
|
||||
|
@ -1429,10 +1431,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
|
||||
let trait_did = bound.def_id();
|
||||
let assoc_item = self
|
||||
.probe_assoc_item(assoc_ident, mode.kind(), hir_ref_id, span, trait_did)
|
||||
.probe_assoc_item(assoc_ident, mode.assoc_tag(), hir_ref_id, span, trait_did)
|
||||
.expect("failed to find associated item");
|
||||
let (def_id, args) =
|
||||
self.lower_assoc_shared(span, assoc_item.def_id, assoc_segment, bound, mode.kind())?;
|
||||
let (def_id, args) = self.lower_assoc_shared(
|
||||
span,
|
||||
assoc_item.def_id,
|
||||
assoc_segment,
|
||||
bound,
|
||||
mode.assoc_tag(),
|
||||
)?;
|
||||
let result = LoweredAssoc::Term(def_id, args);
|
||||
|
||||
if let Some(variant_def_id) = variant_resolution {
|
||||
|
@ -1469,20 +1476,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
self_ty: Ty<'tcx>,
|
||||
block: HirId,
|
||||
span: Span,
|
||||
kind: ty::AssocKind,
|
||||
assoc_tag: ty::AssocTag,
|
||||
) -> Result<Option<(DefId, GenericArgsRef<'tcx>)>, ErrorGuaranteed> {
|
||||
let tcx = self.tcx();
|
||||
|
||||
if !tcx.features().inherent_associated_types() {
|
||||
match kind {
|
||||
// Don't attempt to look up inherent associated types when the feature is not enabled.
|
||||
// Theoretically it'd be fine to do so since we feature-gate their definition site.
|
||||
// However, due to current limitations of the implementation (caused by us performing
|
||||
// selection during HIR ty lowering instead of in the trait solver), IATs can lead to cycle
|
||||
// errors (#108491) which mask the feature-gate error, needlessly confusing users
|
||||
// who use IATs by accident (#113265).
|
||||
ty::AssocKind::Type => return Ok(None),
|
||||
ty::AssocKind::Const => {
|
||||
match assoc_tag {
|
||||
// Don't attempt to look up inherent associated types when the feature is not
|
||||
// enabled. Theoretically it'd be fine to do so since we feature-gate their
|
||||
// definition site. However, due to current limitations of the implementation
|
||||
// (caused by us performing selection during HIR ty lowering instead of in the
|
||||
// trait solver), IATs can lead to cycle errors (#108491) which mask the
|
||||
// feature-gate error, needlessly confusing users who use IATs by accident
|
||||
// (#113265).
|
||||
ty::AssocTag::Type => return Ok(None),
|
||||
ty::AssocTag::Const => {
|
||||
// We also gate the mgca codepath for type-level uses of inherent consts
|
||||
// with the inherent_associated_types feature gate since it relies on the
|
||||
// same machinery and has similar rough edges.
|
||||
|
@ -1494,7 +1502,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
)
|
||||
.emit());
|
||||
}
|
||||
ty::AssocKind::Fn => unreachable!(),
|
||||
ty::AssocTag::Fn => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1503,7 +1511,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
.inherent_impls(adt_did)
|
||||
.iter()
|
||||
.filter_map(|&impl_| {
|
||||
let (item, scope) = self.probe_assoc_item_unchecked(name, kind, block, impl_)?;
|
||||
let (item, scope) =
|
||||
self.probe_assoc_item_unchecked(name, assoc_tag, block, impl_)?;
|
||||
Some((impl_, (item.def_id, scope)))
|
||||
})
|
||||
.collect();
|
||||
|
@ -1542,7 +1551,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
self_ty,
|
||||
|self_ty| {
|
||||
self.select_inherent_assoc_candidates(
|
||||
infcx, name, span, self_ty, param_env, candidates, kind,
|
||||
infcx, name, span, self_ty, param_env, candidates, assoc_tag,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
@ -1570,7 +1579,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
self_ty: Ty<'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
candidates: Vec<(DefId, (DefId, DefId))>,
|
||||
kind: ty::AssocKind,
|
||||
assoc_tag: ty::AssocTag,
|
||||
) -> Result<(DefId, (DefId, DefId)), ErrorGuaranteed> {
|
||||
let tcx = self.tcx();
|
||||
let mut fulfillment_errors = Vec::new();
|
||||
|
@ -1621,7 +1630,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
candidates,
|
||||
fulfillment_errors,
|
||||
span,
|
||||
kind,
|
||||
assoc_tag,
|
||||
)),
|
||||
|
||||
&[applicable_candidate] => Ok(applicable_candidate),
|
||||
|
@ -1640,12 +1649,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
fn probe_assoc_item(
|
||||
&self,
|
||||
ident: Ident,
|
||||
kind: ty::AssocKind,
|
||||
assoc_tag: ty::AssocTag,
|
||||
block: HirId,
|
||||
span: Span,
|
||||
scope: DefId,
|
||||
) -> Option<ty::AssocItem> {
|
||||
let (item, scope) = self.probe_assoc_item_unchecked(ident, kind, block, scope)?;
|
||||
let (item, scope) = self.probe_assoc_item_unchecked(ident, assoc_tag, block, scope)?;
|
||||
self.check_assoc_item(item.def_id, ident, scope, block, span);
|
||||
Some(item)
|
||||
}
|
||||
|
@ -1657,7 +1666,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
fn probe_assoc_item_unchecked(
|
||||
&self,
|
||||
ident: Ident,
|
||||
kind: ty::AssocKind,
|
||||
assoc_tag: ty::AssocTag,
|
||||
block: HirId,
|
||||
scope: DefId,
|
||||
) -> Option<(ty::AssocItem, /*scope*/ DefId)> {
|
||||
|
@ -1670,7 +1679,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let item = tcx
|
||||
.associated_items(scope)
|
||||
.filter_by_name_unhygienic(ident.name)
|
||||
.find(|i| i.kind == kind && i.ident(tcx).normalize_to_macros_2_0() == ident)?;
|
||||
.find(|i| i.as_tag() == assoc_tag && i.ident(tcx).normalize_to_macros_2_0() == ident)?;
|
||||
|
||||
Some((*item, def_scope))
|
||||
}
|
||||
|
@ -1722,9 +1731,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
tcx.associated_items(*trait_def_id)
|
||||
.in_definition_order()
|
||||
.any(|i| {
|
||||
i.kind.namespace() == Namespace::TypeNS
|
||||
i.namespace() == Namespace::TypeNS
|
||||
&& i.ident(tcx).normalize_to_macros_2_0() == assoc_ident
|
||||
&& matches!(i.kind, ty::AssocKind::Type)
|
||||
&& i.is_type()
|
||||
})
|
||||
// Consider only accessible traits
|
||||
&& tcx.visibility(*trait_def_id)
|
||||
|
@ -1770,7 +1779,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
item_def_id,
|
||||
trait_segment,
|
||||
item_segment,
|
||||
ty::AssocKind::Type,
|
||||
ty::AssocTag::Type,
|
||||
) {
|
||||
Ok((item_def_id, item_args)) => {
|
||||
Ty::new_projection_from_args(self.tcx(), item_def_id, item_args)
|
||||
|
@ -1795,7 +1804,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
item_def_id,
|
||||
trait_segment,
|
||||
item_segment,
|
||||
ty::AssocKind::Const,
|
||||
ty::AssocTag::Const,
|
||||
) {
|
||||
Ok((item_def_id, item_args)) => {
|
||||
let uv = ty::UnevaluatedConst::new(item_def_id, item_args);
|
||||
|
@ -1813,7 +1822,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
item_def_id: DefId,
|
||||
trait_segment: &hir::PathSegment<'tcx>,
|
||||
item_segment: &hir::PathSegment<'tcx>,
|
||||
kind: ty::AssocKind,
|
||||
assoc_tag: ty::AssocTag,
|
||||
) -> Result<(DefId, GenericArgsRef<'tcx>), ErrorGuaranteed> {
|
||||
let tcx = self.tcx();
|
||||
|
||||
|
@ -1821,7 +1830,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
debug!(?trait_def_id);
|
||||
|
||||
let Some(self_ty) = opt_self_ty else {
|
||||
return Err(self.error_missing_qpath_self_ty(trait_def_id, span, item_segment, kind));
|
||||
return Err(self.error_missing_qpath_self_ty(
|
||||
trait_def_id,
|
||||
span,
|
||||
item_segment,
|
||||
assoc_tag,
|
||||
));
|
||||
};
|
||||
debug!(?self_ty);
|
||||
|
||||
|
@ -1840,7 +1854,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
trait_def_id: DefId,
|
||||
span: Span,
|
||||
item_segment: &hir::PathSegment<'tcx>,
|
||||
kind: ty::AssocKind,
|
||||
assoc_tag: ty::AssocTag,
|
||||
) -> ErrorGuaranteed {
|
||||
let tcx = self.tcx();
|
||||
let path_str = tcx.def_path_str(trait_def_id);
|
||||
|
@ -1877,7 +1891,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
// FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that
|
||||
// references the trait. Relevant for the first case in
|
||||
// `src/test/ui/associated-types/associated-types-in-ambiguous-context.rs`
|
||||
self.report_ambiguous_assoc(span, &type_names, &[path_str], item_segment.ident.name, kind)
|
||||
self.report_ambiguous_assoc(
|
||||
span,
|
||||
&type_names,
|
||||
&[path_str],
|
||||
item_segment.ident.name,
|
||||
assoc_tag,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn prohibit_generic_args<'a>(
|
||||
|
@ -2862,7 +2882,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let assoc = tcx.associated_items(trait_ref.def_id).find_by_ident_and_kind(
|
||||
tcx,
|
||||
*ident,
|
||||
ty::AssocKind::Fn,
|
||||
ty::AssocTag::Fn,
|
||||
trait_ref.def_id,
|
||||
)?;
|
||||
|
||||
|
|
|
@ -112,14 +112,14 @@ pub(crate) fn enforce_impl_lifetime_params_are_constrained(
|
|||
.flat_map(|def_id| {
|
||||
let item = tcx.associated_item(def_id);
|
||||
match item.kind {
|
||||
ty::AssocKind::Type => {
|
||||
ty::AssocKind::Type { .. } => {
|
||||
if item.defaultness(tcx).has_value() {
|
||||
cgp::parameters_for(tcx, tcx.type_of(def_id).instantiate_identity(), true)
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
ty::AssocKind::Fn | ty::AssocKind::Const => vec![],
|
||||
ty::AssocKind::Fn { .. } | ty::AssocKind::Const { .. } => vec![],
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
|
|
@ -1871,10 +1871,11 @@ impl<'a> State<'a> {
|
|||
fn print_pat(&mut self, pat: &hir::Pat<'_>) {
|
||||
self.maybe_print_comment(pat.span.lo());
|
||||
self.ann.pre(self, AnnNode::Pat(pat));
|
||||
// Pat isn't normalized, but the beauty of it
|
||||
// is that it doesn't matter
|
||||
// Pat isn't normalized, but the beauty of it is that it doesn't matter.
|
||||
match pat.kind {
|
||||
PatKind::Missing => unreachable!(),
|
||||
// Printing `_` isn't ideal for a missing pattern, but it's easy and good enough.
|
||||
// E.g. `fn(u32)` gets printed as `fn(_: u32)`.
|
||||
PatKind::Missing => self.word("_"),
|
||||
PatKind::Wild => self.word("_"),
|
||||
PatKind::Never => self.word("!"),
|
||||
PatKind::Binding(BindingMode(by_ref, mutbl), _, ident, sub) => {
|
||||
|
@ -2164,7 +2165,9 @@ impl<'a> State<'a> {
|
|||
s.end();
|
||||
});
|
||||
if decl.c_variadic {
|
||||
self.word(", ");
|
||||
if !decl.inputs.is_empty() {
|
||||
self.word(", ");
|
||||
}
|
||||
print_arg(self, None);
|
||||
self.word("...");
|
||||
}
|
||||
|
|
|
@ -1089,14 +1089,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
/// This function checks whether the method is not static and does not accept other parameters than `self`.
|
||||
fn has_only_self_parameter(&self, method: &AssocItem) -> bool {
|
||||
match method.kind {
|
||||
ty::AssocKind::Fn => {
|
||||
method.fn_has_self_parameter
|
||||
&& self.tcx.fn_sig(method.def_id).skip_binder().inputs().skip_binder().len()
|
||||
== 1
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
method.is_method()
|
||||
&& self.tcx.fn_sig(method.def_id).skip_binder().inputs().skip_binder().len() == 1
|
||||
}
|
||||
|
||||
/// If the given `HirId` corresponds to a block with a trailing expression, return that expression
|
||||
|
|
|
@ -2588,9 +2588,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.into_iter()
|
||||
.flat_map(|i| self.tcx.associated_items(i).in_definition_order())
|
||||
// Only assoc fn with no receivers.
|
||||
.filter(|item| {
|
||||
matches!(item.kind, ty::AssocKind::Fn) && !item.fn_has_self_parameter
|
||||
})
|
||||
.filter(|item| item.is_fn() && !item.is_method())
|
||||
.filter_map(|item| {
|
||||
// Only assoc fns that return `Self`
|
||||
let fn_sig = self.tcx.fn_sig(item.def_id).skip_binder();
|
||||
|
@ -2603,8 +2601,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return None;
|
||||
}
|
||||
let input_len = fn_sig.inputs().skip_binder().len();
|
||||
let order = !item.name.as_str().starts_with("new");
|
||||
Some((order, item.name, input_len))
|
||||
let name = item.name();
|
||||
let order = !name.as_str().starts_with("new");
|
||||
Some((order, name, input_len))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
items.sort_by_key(|(order, _, _)| *order);
|
||||
|
|
|
@ -616,7 +616,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if let Some((DefKind::AssocFn, def_id)) =
|
||||
self.typeck_results.borrow().type_dependent_def(call_expr.hir_id)
|
||||
&& let Some(assoc) = tcx.opt_associated_item(def_id)
|
||||
&& assoc.fn_has_self_parameter
|
||||
&& assoc.is_method()
|
||||
{
|
||||
Some(*receiver)
|
||||
} else {
|
||||
|
@ -642,8 +642,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
TraitsInScope,
|
||||
|mut ctxt| ctxt.probe_for_similar_candidate(),
|
||||
)
|
||||
&& let ty::AssocKind::Fn = assoc.kind
|
||||
&& assoc.fn_has_self_parameter
|
||||
&& assoc.is_method()
|
||||
{
|
||||
let args = self.infcx.fresh_args_for_item(call_name.span, assoc.def_id);
|
||||
let fn_sig = tcx.fn_sig(assoc.def_id).instantiate(tcx, args);
|
||||
|
@ -684,10 +683,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.all(|(expected, found)| self.may_coerce(*expected, *found))
|
||||
&& fn_sig.inputs()[1..].len() == input_types.len()
|
||||
{
|
||||
let assoc_name = assoc.name();
|
||||
err.span_suggestion_verbose(
|
||||
call_name.span,
|
||||
format!("you might have meant to use `{}`", assoc.name),
|
||||
assoc.name,
|
||||
format!("you might have meant to use `{}`", assoc_name),
|
||||
assoc_name,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
return;
|
||||
|
@ -707,7 +707,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
tcx.def_span(assoc.def_id),
|
||||
format!(
|
||||
"there's is a method with similar name `{}`, but the arguments don't match",
|
||||
assoc.name,
|
||||
assoc.name(),
|
||||
),
|
||||
);
|
||||
return;
|
||||
|
@ -719,7 +719,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
format!(
|
||||
"there's is a method with similar name `{}`, but their argument count \
|
||||
doesn't match",
|
||||
assoc.name,
|
||||
assoc.name(),
|
||||
),
|
||||
);
|
||||
return;
|
||||
|
|
|
@ -314,7 +314,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
|
|||
item_def_id: DefId,
|
||||
item_segment: &rustc_hir::PathSegment<'tcx>,
|
||||
poly_trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
_kind: ty::AssocKind,
|
||||
_assoc_tag: ty::AssocTag,
|
||||
) -> Result<(DefId, ty::GenericArgsRef<'tcx>), ErrorGuaranteed> {
|
||||
let trait_ref = self.instantiate_binder_with_fresh_vars(
|
||||
span,
|
||||
|
|
|
@ -381,9 +381,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let mut suggestions = methods
|
||||
.iter()
|
||||
.filter_map(|conversion_method| {
|
||||
let conversion_method_name = conversion_method.name();
|
||||
let receiver_method_ident = expr.method_ident();
|
||||
if let Some(method_ident) = receiver_method_ident
|
||||
&& method_ident.name == conversion_method.name
|
||||
&& method_ident.name == conversion_method_name
|
||||
{
|
||||
return None; // do not suggest code that is already there (#53348)
|
||||
}
|
||||
|
@ -391,20 +392,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let method_call_list = [sym::to_vec, sym::to_string];
|
||||
let mut sugg = if let ExprKind::MethodCall(receiver_method, ..) = expr.kind
|
||||
&& receiver_method.ident.name == sym::clone
|
||||
&& method_call_list.contains(&conversion_method.name)
|
||||
&& method_call_list.contains(&conversion_method_name)
|
||||
// If receiver is `.clone()` and found type has one of those methods,
|
||||
// we guess that the user wants to convert from a slice type (`&[]` or `&str`)
|
||||
// to an owned type (`Vec` or `String`). These conversions clone internally,
|
||||
// so we remove the user's `clone` call.
|
||||
{
|
||||
vec![(receiver_method.ident.span, conversion_method.name.to_string())]
|
||||
vec![(receiver_method.ident.span, conversion_method_name.to_string())]
|
||||
} else if expr.precedence() < ExprPrecedence::Unambiguous {
|
||||
vec![
|
||||
(expr.span.shrink_to_lo(), "(".to_string()),
|
||||
(expr.span.shrink_to_hi(), format!(").{}()", conversion_method.name)),
|
||||
(expr.span.shrink_to_hi(), format!(").{}()", conversion_method_name)),
|
||||
]
|
||||
} else {
|
||||
vec![(expr.span.shrink_to_hi(), format!(".{}()", conversion_method.name))]
|
||||
vec![(expr.span.shrink_to_hi(), format!(".{}()", conversion_method_name))]
|
||||
};
|
||||
let struct_pat_shorthand_field =
|
||||
self.tcx.hir_maybe_get_struct_pattern_shorthand_field(expr);
|
||||
|
|
|
@ -265,7 +265,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
|
|||
let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer(()), span, .. }) = node.ty()
|
||||
{
|
||||
if let Some(item) = tcx.opt_associated_item(def_id.into())
|
||||
&& let ty::AssocKind::Const = item.kind
|
||||
&& let ty::AssocKind::Const { .. } = item.kind
|
||||
&& let ty::AssocItemContainer::Impl = item.container
|
||||
&& let Some(trait_item_def_id) = item.trait_item_def_id
|
||||
{
|
||||
|
|
|
@ -379,7 +379,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
};
|
||||
|
||||
let def_id = method_item.def_id;
|
||||
if method_item.kind != ty::AssocKind::Fn {
|
||||
if !method_item.is_fn() {
|
||||
span_bug!(tcx.def_span(def_id), "expected `{m_name}` to be an associated function");
|
||||
}
|
||||
|
||||
|
@ -529,7 +529,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
let def_kind = pick.item.kind.as_def_kind();
|
||||
let def_kind = pick.item.as_def_kind();
|
||||
tcx.check_stability(pick.item.def_id, Some(expr_id), span, Some(method_name.span));
|
||||
Ok((def_kind, pick.item.def_id))
|
||||
}
|
||||
|
|
|
@ -992,7 +992,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
|
||||
fn matches_return_type(&self, method: ty::AssocItem, expected: Ty<'tcx>) -> bool {
|
||||
match method.kind {
|
||||
ty::AssocKind::Fn => self.probe(|_| {
|
||||
ty::AssocKind::Fn { .. } => self.probe(|_| {
|
||||
let args = self.fresh_args_for_item(self.span, method.def_id);
|
||||
let fty = self.tcx.fn_sig(method.def_id).instantiate(self.tcx, args);
|
||||
let fty = self.instantiate_binder_with_fresh_vars(self.span, infer::FnCall, fty);
|
||||
|
@ -1583,7 +1583,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
},
|
||||
None,
|
||||
) {
|
||||
self.private_candidate.set(Some((pick.item.kind.as_def_kind(), pick.item.def_id)));
|
||||
self.private_candidate.set(Some((pick.item.as_def_kind(), pick.item.def_id)));
|
||||
}
|
||||
}
|
||||
None
|
||||
|
@ -1671,16 +1671,7 @@ impl<'tcx> Pick<'tcx> {
|
|||
/// Do not use for type checking.
|
||||
pub(crate) fn differs_from(&self, other: &Self) -> bool {
|
||||
let Self {
|
||||
item:
|
||||
AssocItem {
|
||||
def_id,
|
||||
name: _,
|
||||
kind: _,
|
||||
container: _,
|
||||
trait_item_def_id: _,
|
||||
fn_has_self_parameter: _,
|
||||
opt_rpitit_info: _,
|
||||
},
|
||||
item: AssocItem { def_id, kind: _, container: _, trait_item_def_id: _ },
|
||||
kind: _,
|
||||
import_ids: _,
|
||||
autoderefs: _,
|
||||
|
@ -1703,7 +1694,7 @@ impl<'tcx> Pick<'tcx> {
|
|||
if self.unstable_candidates.is_empty() {
|
||||
return;
|
||||
}
|
||||
let def_kind = self.item.kind.as_def_kind();
|
||||
let def_kind = self.item.as_def_kind();
|
||||
tcx.node_span_lint(lint::builtin::UNSTABLE_NAME_COLLISIONS, scope_expr_id, span, |lint| {
|
||||
lint.primary_message(format!(
|
||||
"{} {} with this name may be added to the standard library in the future",
|
||||
|
@ -1712,7 +1703,7 @@ impl<'tcx> Pick<'tcx> {
|
|||
));
|
||||
|
||||
match (self.item.kind, self.item.container) {
|
||||
(ty::AssocKind::Fn, _) => {
|
||||
(ty::AssocKind::Fn { .. }, _) => {
|
||||
// FIXME: This should be a `span_suggestion` instead of `help`
|
||||
// However `self.span` only
|
||||
// highlights the method name, so we can't use it. Also consider reusing
|
||||
|
@ -1723,17 +1714,12 @@ impl<'tcx> Pick<'tcx> {
|
|||
tcx.def_path_str(self.item.def_id),
|
||||
));
|
||||
}
|
||||
(ty::AssocKind::Const, ty::AssocItemContainer::Trait) => {
|
||||
(ty::AssocKind::Const { name }, ty::AssocItemContainer::Trait) => {
|
||||
let def_id = self.item.container_id(tcx);
|
||||
lint.span_suggestion(
|
||||
span,
|
||||
"use the fully qualified path to the associated const",
|
||||
format!(
|
||||
"<{} as {}>::{}",
|
||||
self.self_ty,
|
||||
tcx.def_path_str(def_id),
|
||||
self.item.name
|
||||
),
|
||||
format!("<{} as {}>::{}", self.self_ty, tcx.def_path_str(def_id), name),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
|
@ -2222,7 +2208,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
let best_name = {
|
||||
let names = applicable_close_candidates
|
||||
.iter()
|
||||
.map(|cand| cand.name)
|
||||
.map(|cand| cand.name())
|
||||
.collect::<Vec<Symbol>>();
|
||||
find_best_match_for_name_with_substrings(
|
||||
&names,
|
||||
|
@ -2234,10 +2220,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
applicable_close_candidates
|
||||
.iter()
|
||||
.find(|cand| self.matches_by_doc_alias(cand.def_id))
|
||||
.map(|cand| cand.name)
|
||||
.map(|cand| cand.name())
|
||||
});
|
||||
Ok(best_name.and_then(|best_name| {
|
||||
applicable_close_candidates.into_iter().find(|method| method.name == best_name)
|
||||
applicable_close_candidates
|
||||
.into_iter()
|
||||
.find(|method| method.name() == best_name)
|
||||
}))
|
||||
}
|
||||
})
|
||||
|
@ -2252,10 +2240,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
// In Path mode (i.e., resolving a value like `T::next`), consider any
|
||||
// associated value (i.e., methods, constants) but not types.
|
||||
match self.mode {
|
||||
Mode::MethodCall => item.fn_has_self_parameter,
|
||||
Mode::MethodCall => item.is_method(),
|
||||
Mode::Path => match item.kind {
|
||||
ty::AssocKind::Type => false,
|
||||
ty::AssocKind::Fn | ty::AssocKind::Const => true,
|
||||
ty::AssocKind::Type { .. } => false,
|
||||
ty::AssocKind::Fn { .. } | ty::AssocKind::Const { .. } => true,
|
||||
},
|
||||
}
|
||||
// FIXME -- check for types that deref to `Self`,
|
||||
|
@ -2277,7 +2265,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
impl_ty: Ty<'tcx>,
|
||||
args: GenericArgsRef<'tcx>,
|
||||
) -> (Ty<'tcx>, Option<Ty<'tcx>>) {
|
||||
if item.kind == ty::AssocKind::Fn && self.mode == Mode::MethodCall {
|
||||
if item.is_fn() && self.mode == Mode::MethodCall {
|
||||
let sig = self.xform_method_sig(item.def_id, args);
|
||||
(sig.inputs()[0], Some(sig.output()))
|
||||
} else {
|
||||
|
@ -2328,8 +2316,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
/// Determine if the given associated item type is relevant in the current context.
|
||||
fn is_relevant_kind_for_mode(&self, kind: ty::AssocKind) -> bool {
|
||||
match (self.mode, kind) {
|
||||
(Mode::MethodCall, ty::AssocKind::Fn) => true,
|
||||
(Mode::Path, ty::AssocKind::Const | ty::AssocKind::Fn) => true,
|
||||
(Mode::MethodCall, ty::AssocKind::Fn { .. }) => true,
|
||||
(Mode::Path, ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. }) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -2411,7 +2399,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
match edit_distance_with_substrings(
|
||||
name.as_str(),
|
||||
x.name.as_str(),
|
||||
x.name().as_str(),
|
||||
max_dist,
|
||||
) {
|
||||
Some(d) => d > 0,
|
||||
|
|
|
@ -713,7 +713,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
&& let Some(candidate) = tcx.associated_items(impl_def_id).find_by_ident_and_kind(
|
||||
self.tcx,
|
||||
item_ident,
|
||||
ty::AssocKind::Type,
|
||||
ty::AssocTag::Type,
|
||||
impl_def_id,
|
||||
)
|
||||
&& let Some(adt_def) = tcx.type_of(candidate.def_id).skip_binder().ty_adt_def()
|
||||
|
@ -1442,7 +1442,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if let Some(assoc) = self.associated_value(*def_id, item_ident) {
|
||||
// Check for both mode is the same so we avoid suggesting
|
||||
// incorrect associated item.
|
||||
match (mode, assoc.fn_has_self_parameter, source) {
|
||||
match (mode, assoc.is_method(), source) {
|
||||
(Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
|
||||
// We check that the suggest type is actually
|
||||
// different from the received one
|
||||
|
@ -1722,7 +1722,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// that had unsatisfied trait bounds
|
||||
if unsatisfied_predicates.is_empty()
|
||||
// ...or if we already suggested that name because of `rustc_confusable` annotation.
|
||||
&& Some(similar_candidate.name) != confusable_suggested
|
||||
&& Some(similar_candidate.name()) != confusable_suggested
|
||||
{
|
||||
self.find_likely_intended_associated_item(
|
||||
&mut err,
|
||||
|
@ -1819,12 +1819,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
mode: Mode,
|
||||
) {
|
||||
let tcx = self.tcx;
|
||||
let def_kind = similar_candidate.kind.as_def_kind();
|
||||
let def_kind = similar_candidate.as_def_kind();
|
||||
let an = self.tcx.def_kind_descr_article(def_kind, similar_candidate.def_id);
|
||||
let similar_candidate_name = similar_candidate.name();
|
||||
let msg = format!(
|
||||
"there is {an} {} `{}` with a similar name",
|
||||
self.tcx.def_kind_descr(def_kind, similar_candidate.def_id),
|
||||
similar_candidate.name,
|
||||
similar_candidate_name,
|
||||
);
|
||||
// Methods are defined within the context of a struct and their first parameter
|
||||
// is always `self`, which represents the instance of the struct the method is
|
||||
|
@ -1834,7 +1835,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let ty_args = self.infcx.fresh_args_for_item(span, similar_candidate.def_id);
|
||||
let fn_sig = tcx.fn_sig(similar_candidate.def_id).instantiate(tcx, ty_args);
|
||||
let fn_sig = self.instantiate_binder_with_fresh_vars(span, infer::FnCall, fn_sig);
|
||||
if similar_candidate.fn_has_self_parameter {
|
||||
if similar_candidate.is_method() {
|
||||
if let Some(args) = args
|
||||
&& fn_sig.inputs()[1..].len() == args.len()
|
||||
{
|
||||
|
@ -1843,7 +1844,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
err.span_suggestion_verbose(
|
||||
span,
|
||||
msg,
|
||||
similar_candidate.name,
|
||||
similar_candidate_name,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
|
@ -1865,7 +1866,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
err.span_suggestion_verbose(
|
||||
span,
|
||||
msg,
|
||||
similar_candidate.name,
|
||||
similar_candidate_name,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
|
@ -1878,7 +1879,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
err.span_suggestion_verbose(
|
||||
span,
|
||||
msg,
|
||||
similar_candidate.name,
|
||||
similar_candidate_name,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
|
@ -1902,7 +1903,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
{
|
||||
if let Some(candidates) = find_attr!(self.tcx.get_all_attrs(inherent_method.def_id), AttributeKind::Confusables{symbols, ..} => symbols)
|
||||
&& candidates.contains(&item_name.name)
|
||||
&& let ty::AssocKind::Fn = inherent_method.kind
|
||||
&& inherent_method.is_fn()
|
||||
{
|
||||
let args =
|
||||
ty::GenericArgs::identity_for_item(self.tcx, inherent_method.def_id)
|
||||
|
@ -1918,6 +1919,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
infer::FnCall,
|
||||
fn_sig,
|
||||
);
|
||||
let name = inherent_method.name();
|
||||
if let Some(ref args) = call_args
|
||||
&& fn_sig.inputs()[1..]
|
||||
.iter()
|
||||
|
@ -1927,20 +1929,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
{
|
||||
err.span_suggestion_verbose(
|
||||
item_name.span,
|
||||
format!("you might have meant to use `{}`", inherent_method.name),
|
||||
inherent_method.name,
|
||||
format!("you might have meant to use `{}`", name),
|
||||
name,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
return Some(inherent_method.name);
|
||||
return Some(name);
|
||||
} else if let None = call_args {
|
||||
err.span_note(
|
||||
self.tcx.def_span(inherent_method.def_id),
|
||||
format!(
|
||||
"you might have meant to use method `{}`",
|
||||
inherent_method.name,
|
||||
),
|
||||
format!("you might have meant to use method `{}`", name),
|
||||
);
|
||||
return Some(inherent_method.name);
|
||||
return Some(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2116,8 +2115,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Only assoc fn with no receivers and only if
|
||||
// they are resolvable
|
||||
.filter(|item| {
|
||||
matches!(item.kind, ty::AssocKind::Fn)
|
||||
&& !item.fn_has_self_parameter
|
||||
matches!(item.kind, ty::AssocKind::Fn { has_self: false, .. })
|
||||
&& self
|
||||
.probe_for_name(
|
||||
Mode::Path,
|
||||
|
@ -2261,7 +2259,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
};
|
||||
|
||||
let assoc = self.associated_value(assoc_did, item_name)?;
|
||||
if assoc.kind != ty::AssocKind::Fn {
|
||||
if !assoc.is_fn() {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -3208,7 +3206,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// If this method receives `&self`, then the provided
|
||||
// argument _should_ coerce, so it's valid to suggest
|
||||
// just changing the path.
|
||||
&& pick.item.fn_has_self_parameter
|
||||
&& pick.item.is_method()
|
||||
&& let Some(self_ty) =
|
||||
self.tcx.fn_sig(pick.item.def_id).instantiate_identity().inputs().skip_binder().get(0)
|
||||
&& self_ty.is_ref()
|
||||
|
@ -3560,7 +3558,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|| (("Pin::new" == *pre)
|
||||
&& ((sym::as_ref == item_name.name) || !unpin))
|
||||
|| inputs_len.is_some_and(|inputs_len| {
|
||||
pick.item.kind == ty::AssocKind::Fn
|
||||
pick.item.is_fn()
|
||||
&& self
|
||||
.tcx
|
||||
.fn_sig(pick.item.def_id)
|
||||
|
@ -3618,7 +3616,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
&& pick.autoderefs == 0
|
||||
// Check that the method of the same name that was found on the new `Pin<T>`
|
||||
// receiver has the same number of arguments that appear in the user's code.
|
||||
&& inputs_len.is_some_and(|inputs_len| pick.item.kind == ty::AssocKind::Fn && self.tcx.fn_sig(pick.item.def_id).skip_binder().skip_binder().inputs().len() == inputs_len)
|
||||
&& inputs_len.is_some_and(|inputs_len| pick.item.is_fn() && self.tcx.fn_sig(pick.item.def_id).skip_binder().skip_binder().inputs().len() == inputs_len)
|
||||
{
|
||||
let indent = self
|
||||
.tcx
|
||||
|
@ -3756,7 +3754,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
&& self
|
||||
.associated_value(info.def_id, item_name)
|
||||
.filter(|item| {
|
||||
if let ty::AssocKind::Fn = item.kind {
|
||||
if item.is_fn() {
|
||||
let id = item
|
||||
.def_id
|
||||
.as_local()
|
||||
|
@ -4279,17 +4277,17 @@ fn print_disambiguation_help<'tcx>(
|
|||
item: ty::AssocItem,
|
||||
) -> Option<String> {
|
||||
let trait_impl_type = trait_ref.self_ty().peel_refs();
|
||||
let trait_ref = if item.fn_has_self_parameter {
|
||||
let trait_ref = if item.is_method() {
|
||||
trait_ref.print_only_trait_name().to_string()
|
||||
} else {
|
||||
format!("<{} as {}>", trait_ref.args[0], trait_ref.print_only_trait_name())
|
||||
};
|
||||
Some(
|
||||
if matches!(item.kind, ty::AssocKind::Fn)
|
||||
if item.is_fn()
|
||||
&& let SelfSource::MethodCall(receiver) = source
|
||||
&& let Some(args) = args
|
||||
{
|
||||
let def_kind_descr = tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id);
|
||||
let def_kind_descr = tcx.def_kind_descr(item.as_def_kind(), item.def_id);
|
||||
let item_name = item.ident(tcx);
|
||||
let first_input =
|
||||
tcx.fn_sig(item.def_id).instantiate_identity().skip_binder().inputs().get(0);
|
||||
|
@ -4304,7 +4302,7 @@ fn print_disambiguation_help<'tcx>(
|
|||
let args = if let Some(first_arg_type) = first_arg_type
|
||||
&& (first_arg_type == tcx.types.self_param
|
||||
|| first_arg_type == trait_impl_type
|
||||
|| item.fn_has_self_parameter)
|
||||
|| item.is_method())
|
||||
{
|
||||
Some(receiver)
|
||||
} else {
|
||||
|
|
|
@ -372,7 +372,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.associated_item_def_ids(def_id)
|
||||
.iter()
|
||||
.find(|item_def_id| {
|
||||
self.tcx.associated_item(*item_def_id).name == sym::Output
|
||||
self.tcx.associated_item(*item_def_id).name() == sym::Output
|
||||
})
|
||||
.cloned()
|
||||
});
|
||||
|
|
|
@ -855,11 +855,11 @@ impl<'tcx> LateContext<'tcx> {
|
|||
&self,
|
||||
self_ty: Ty<'tcx>,
|
||||
trait_id: DefId,
|
||||
name: &str,
|
||||
name: Symbol,
|
||||
) -> Option<Ty<'tcx>> {
|
||||
let tcx = self.tcx;
|
||||
tcx.associated_items(trait_id)
|
||||
.find_by_ident_and_kind(tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id)
|
||||
.find_by_ident_and_kind(tcx, Ident::with_dummy_span(name), ty::AssocTag::Type, trait_id)
|
||||
.and_then(|assoc| {
|
||||
let proj = Ty::new_projection(tcx, assoc.def_id, [self_ty]);
|
||||
tcx.try_normalize_erasing_regions(self.typing_env(), proj).ok()
|
||||
|
|
|
@ -69,7 +69,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait {
|
|||
&& let ty::Dynamic(data, _, ty::Dyn) = self_ty.kind()
|
||||
&& let Some(self_principal) = data.principal()
|
||||
// `<T as Deref>::Target` is `dyn target_principal`
|
||||
&& let Some(target) = cx.get_associated_type(self_ty, did, "Target")
|
||||
&& let Some(target) = cx.get_associated_type(self_ty, did, sym::Target)
|
||||
&& let ty::Dynamic(data, _, ty::Dyn) = target.kind()
|
||||
&& let Some(target_principal) = data.principal()
|
||||
// `target_principal` is a supertrait of `t_principal`
|
||||
|
|
|
@ -1332,29 +1332,30 @@ impl<'a> CrateMetadataRef<'a> {
|
|||
}
|
||||
|
||||
fn get_associated_item(self, id: DefIndex, sess: &'a Session) -> ty::AssocItem {
|
||||
let name = if self.root.tables.opt_rpitit_info.get(self, id).is_some() {
|
||||
kw::Empty
|
||||
} else {
|
||||
self.item_name(id)
|
||||
};
|
||||
let (kind, has_self) = match self.def_kind(id) {
|
||||
DefKind::AssocConst => (ty::AssocKind::Const, false),
|
||||
DefKind::AssocFn => (ty::AssocKind::Fn, self.get_fn_has_self_parameter(id, sess)),
|
||||
DefKind::AssocTy => (ty::AssocKind::Type, false),
|
||||
let kind = match self.def_kind(id) {
|
||||
DefKind::AssocConst => ty::AssocKind::Const { name: self.item_name(id) },
|
||||
DefKind::AssocFn => ty::AssocKind::Fn {
|
||||
name: self.item_name(id),
|
||||
has_self: self.get_fn_has_self_parameter(id, sess),
|
||||
},
|
||||
DefKind::AssocTy => {
|
||||
let data = if let Some(rpitit_info) = self.root.tables.opt_rpitit_info.get(self, id)
|
||||
{
|
||||
ty::AssocTypeData::Rpitit(rpitit_info.decode(self))
|
||||
} else {
|
||||
ty::AssocTypeData::Normal(self.item_name(id))
|
||||
};
|
||||
ty::AssocKind::Type { data }
|
||||
}
|
||||
_ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)),
|
||||
};
|
||||
let container = self.root.tables.assoc_container.get(self, id).unwrap();
|
||||
let opt_rpitit_info =
|
||||
self.root.tables.opt_rpitit_info.get(self, id).map(|d| d.decode(self));
|
||||
|
||||
ty::AssocItem {
|
||||
name,
|
||||
kind,
|
||||
def_id: self.local_def_id(id),
|
||||
trait_item_def_id: self.get_trait_item_def_id(id),
|
||||
container,
|
||||
fn_has_self_parameter: has_self,
|
||||
opt_rpitit_info,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1338,7 +1338,7 @@ fn should_encode_const(def_kind: DefKind) -> bool {
|
|||
fn should_encode_fn_impl_trait_in_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
|
||||
if let Some(assoc_item) = tcx.opt_associated_item(def_id)
|
||||
&& assoc_item.container == ty::AssocItemContainer::Trait
|
||||
&& assoc_item.kind == ty::AssocKind::Fn
|
||||
&& assoc_item.is_fn()
|
||||
{
|
||||
true
|
||||
} else {
|
||||
|
@ -1691,7 +1691,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
|
||||
match item.container {
|
||||
AssocItemContainer::Trait => {
|
||||
if let ty::AssocKind::Type = item.kind {
|
||||
if item.is_type() {
|
||||
self.encode_explicit_item_bounds(def_id);
|
||||
self.encode_explicit_item_self_bounds(def_id);
|
||||
if tcx.is_conditionally_const(def_id) {
|
||||
|
@ -1706,7 +1706,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
if let Some(rpitit_info) = item.opt_rpitit_info {
|
||||
if let ty::AssocKind::Type { data: ty::AssocTypeData::Rpitit(rpitit_info) } = item.kind {
|
||||
record!(self.tables.opt_rpitit_info[def_id] <- rpitit_info);
|
||||
if matches!(rpitit_info, ty::ImplTraitInTraitData::Trait { .. }) {
|
||||
record_array!(
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
//! This module used to contain a type called `Map`. That type has since been
|
||||
//! eliminated, and all its methods are now on `TyCtxt`. But the module name
|
||||
//! stays as `map` because there isn't an obviously better name for it.
|
||||
|
||||
use rustc_abi::ExternAbi;
|
||||
use rustc_ast::visit::{VisitorResult, walk_list};
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
|
@ -18,16 +22,6 @@ use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
|
|||
use crate::query::LocalCrate;
|
||||
use crate::ty::TyCtxt;
|
||||
|
||||
// FIXME: the structure was necessary in the past but now it
|
||||
// only serves as "namespace" for HIR-related methods, and can be
|
||||
// removed if all the methods are reasonably renamed and moved to tcx
|
||||
// (https://github.com/rust-lang/rust/pull/118256#issuecomment-1826442834).
|
||||
#[allow(unused)] // FIXME: temporary
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Map<'hir> {
|
||||
pub(super) tcx: TyCtxt<'hir>,
|
||||
}
|
||||
|
||||
/// An iterator that walks up the ancestor tree of a given `HirId`.
|
||||
/// Constructed using `tcx.hir_parent_iter(hir_id)`.
|
||||
struct ParentHirIterator<'tcx> {
|
||||
|
@ -335,7 +329,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
|
||||
/// Returns an iterator of the `DefId`s for all body-owners in this
|
||||
/// crate. If you would prefer to iterate over the bodies
|
||||
/// themselves, you can do `self.hir().krate().body_ids.iter()`.
|
||||
/// themselves, you can do `self.hir_crate(()).body_ids.iter()`.
|
||||
#[inline]
|
||||
pub fn hir_body_owners(self) -> impl Iterator<Item = LocalDefId> {
|
||||
self.hir_crate_items(()).body_owners.iter().copied()
|
||||
|
|
|
@ -116,11 +116,6 @@ impl ModuleItems {
|
|||
}
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
#[inline(always)]
|
||||
pub fn hir(self) -> map::Map<'tcx> {
|
||||
map::Map { tcx: self }
|
||||
}
|
||||
|
||||
pub fn parent_module(self, id: HirId) -> LocalModDefId {
|
||||
if !id.is_owner() && self.def_kind(id.owner) == DefKind::Mod {
|
||||
LocalModDefId::new_unchecked(id.owner.def_id)
|
||||
|
|
|
@ -1636,8 +1636,8 @@ pub fn find_self_call<'tcx>(
|
|||
&body[block].terminator
|
||||
&& let Operand::Constant(box ConstOperand { const_, .. }) = func
|
||||
&& let ty::FnDef(def_id, fn_args) = *const_.ty().kind()
|
||||
&& let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
|
||||
tcx.opt_associated_item(def_id)
|
||||
&& let Some(item) = tcx.opt_associated_item(def_id)
|
||||
&& item.is_method()
|
||||
&& let [Spanned { node: Operand::Move(self_place) | Operand::Copy(self_place), .. }, ..] =
|
||||
**args
|
||||
{
|
||||
|
|
|
@ -161,11 +161,11 @@ rustc_queries! {
|
|||
|
||||
/// Represents crate as a whole (as distinct from the top-level crate module).
|
||||
///
|
||||
/// If you call `hir_crate` (e.g., indirectly by calling `tcx.hir_crate()`),
|
||||
/// we will have to assume that any change means that you need to be recompiled.
|
||||
/// This is because the `hir_crate` query gives you access to all other items.
|
||||
/// To avoid this fate, do not call `tcx.hir_crate()`; instead,
|
||||
/// prefer wrappers like [`TyCtxt::hir_visit_all_item_likes_in_crate`].
|
||||
/// If you call `tcx.hir_crate(())` we will have to assume that any change
|
||||
/// means that you need to be recompiled. This is because the `hir_crate`
|
||||
/// query gives you access to all other items. To avoid this fate, do not
|
||||
/// call `tcx.hir_crate(())`; instead, prefer wrappers like
|
||||
/// [`TyCtxt::hir_visit_all_item_likes_in_crate`].
|
||||
query hir_crate(key: ()) -> &'tcx Crate<'tcx> {
|
||||
arena_cache
|
||||
eval_always
|
||||
|
@ -197,7 +197,7 @@ rustc_queries! {
|
|||
|
||||
/// Gives access to the HIR node's parent for the HIR owner `key`.
|
||||
///
|
||||
/// This can be conveniently accessed by methods on `tcx.hir()`.
|
||||
/// This can be conveniently accessed by `tcx.hir_*` methods.
|
||||
/// Avoid calling this query directly.
|
||||
query hir_owner_parent(key: hir::OwnerId) -> hir::HirId {
|
||||
desc { |tcx| "getting HIR parent of `{}`", tcx.def_path_str(key) }
|
||||
|
@ -205,7 +205,7 @@ rustc_queries! {
|
|||
|
||||
/// Gives access to the HIR nodes and bodies inside `key` if it's a HIR owner.
|
||||
///
|
||||
/// This can be conveniently accessed by methods on `tcx.hir()`.
|
||||
/// This can be conveniently accessed by `tcx.hir_*` methods.
|
||||
/// Avoid calling this query directly.
|
||||
query opt_hir_owner_nodes(key: LocalDefId) -> Option<&'tcx hir::OwnerNodes<'tcx>> {
|
||||
desc { |tcx| "getting HIR owner items in `{}`", tcx.def_path_str(key) }
|
||||
|
@ -214,7 +214,7 @@ rustc_queries! {
|
|||
|
||||
/// Gives access to the HIR attributes inside the HIR owner `key`.
|
||||
///
|
||||
/// This can be conveniently accessed by methods on `tcx.hir()`.
|
||||
/// This can be conveniently accessed by `tcx.hir_*` methods.
|
||||
/// Avoid calling this query directly.
|
||||
query hir_attr_map(key: hir::OwnerId) -> &'tcx hir::AttributeMap<'tcx> {
|
||||
desc { |tcx| "getting HIR owner attributes in `{}`", tcx.def_path_str(key) }
|
||||
|
|
|
@ -5,7 +5,7 @@ use rustc_hir::lang_items::LangItem;
|
|||
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
|
||||
use rustc_span::Span;
|
||||
|
||||
use crate::ty::{self, Ty, TyCtxt};
|
||||
use crate::ty::{Ty, TyCtxt};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
|
||||
pub enum PointerCoercion {
|
||||
|
@ -133,7 +133,7 @@ impl OverloadedDeref {
|
|||
};
|
||||
tcx.associated_items(trait_def_id)
|
||||
.in_definition_order()
|
||||
.find(|m| m.kind == ty::AssocKind::Fn)
|
||||
.find(|item| item.is_fn())
|
||||
.unwrap()
|
||||
.def_id
|
||||
}
|
||||
|
|
|
@ -18,27 +18,33 @@ pub enum AssocItemContainer {
|
|||
#[derive(Copy, Clone, Debug, PartialEq, HashStable, Eq, Hash, Encodable, Decodable)]
|
||||
pub struct AssocItem {
|
||||
pub def_id: DefId,
|
||||
pub name: Symbol,
|
||||
pub kind: AssocKind,
|
||||
pub container: AssocItemContainer,
|
||||
|
||||
/// If this is an item in an impl of a trait then this is the `DefId` of
|
||||
/// the associated item on the trait that this implements.
|
||||
pub trait_item_def_id: Option<DefId>,
|
||||
|
||||
/// Whether this is a method with an explicit self
|
||||
/// as its first parameter, allowing method calls.
|
||||
pub fn_has_self_parameter: bool,
|
||||
|
||||
/// `Some` if the associated item (an associated type) comes from the
|
||||
/// return-position `impl Trait` in trait desugaring. The `ImplTraitInTraitData`
|
||||
/// provides additional information about its source.
|
||||
pub opt_rpitit_info: Option<ty::ImplTraitInTraitData>,
|
||||
}
|
||||
|
||||
impl AssocItem {
|
||||
// Gets the identifier, if it has one.
|
||||
pub fn opt_name(&self) -> Option<Symbol> {
|
||||
match self.kind {
|
||||
ty::AssocKind::Type { data: AssocTypeData::Normal(name) } => Some(name),
|
||||
ty::AssocKind::Type { data: AssocTypeData::Rpitit(_) } => None,
|
||||
ty::AssocKind::Const { name } => Some(name),
|
||||
ty::AssocKind::Fn { name, .. } => Some(name),
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the identifier name. Aborts if it lacks one, i.e. is an RPITIT
|
||||
// associated type.
|
||||
pub fn name(&self) -> Symbol {
|
||||
self.opt_name().expect("name of non-Rpitit assoc item")
|
||||
}
|
||||
|
||||
pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
|
||||
Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())
|
||||
Ident::new(self.name(), tcx.def_ident_span(self.def_id).unwrap())
|
||||
}
|
||||
|
||||
/// Gets the defaultness of the associated item.
|
||||
|
@ -78,35 +84,65 @@ impl AssocItem {
|
|||
|
||||
pub fn signature(&self, tcx: TyCtxt<'_>) -> String {
|
||||
match self.kind {
|
||||
ty::AssocKind::Fn => {
|
||||
ty::AssocKind::Fn { .. } => {
|
||||
// We skip the binder here because the binder would deanonymize all
|
||||
// late-bound regions, and we don't want method signatures to show up
|
||||
// `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound
|
||||
// regions just fine, showing `fn(&MyType)`.
|
||||
tcx.fn_sig(self.def_id).instantiate_identity().skip_binder().to_string()
|
||||
}
|
||||
ty::AssocKind::Type => format!("type {};", self.name),
|
||||
ty::AssocKind::Const => {
|
||||
format!(
|
||||
"const {}: {:?};",
|
||||
self.name,
|
||||
tcx.type_of(self.def_id).instantiate_identity()
|
||||
)
|
||||
ty::AssocKind::Type { .. } => format!("type {};", self.name()),
|
||||
ty::AssocKind::Const { name } => {
|
||||
format!("const {}: {:?};", name, tcx.type_of(self.def_id).instantiate_identity())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn descr(&self) -> &'static str {
|
||||
match self.kind {
|
||||
ty::AssocKind::Const => "associated const",
|
||||
ty::AssocKind::Fn if self.fn_has_self_parameter => "method",
|
||||
ty::AssocKind::Fn => "associated function",
|
||||
ty::AssocKind::Type => "associated type",
|
||||
ty::AssocKind::Const { .. } => "associated const",
|
||||
ty::AssocKind::Fn { has_self: true, .. } => "method",
|
||||
ty::AssocKind::Fn { has_self: false, .. } => "associated function",
|
||||
ty::AssocKind::Type { .. } => "associated type",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn namespace(&self) -> Namespace {
|
||||
match self.kind {
|
||||
ty::AssocKind::Type { .. } => Namespace::TypeNS,
|
||||
ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => Namespace::ValueNS,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_def_kind(&self) -> DefKind {
|
||||
match self.kind {
|
||||
AssocKind::Const { .. } => DefKind::AssocConst,
|
||||
AssocKind::Fn { .. } => DefKind::AssocFn,
|
||||
AssocKind::Type { .. } => DefKind::AssocTy,
|
||||
}
|
||||
}
|
||||
pub fn is_type(&self) -> bool {
|
||||
matches!(self.kind, ty::AssocKind::Type { .. })
|
||||
}
|
||||
|
||||
pub fn is_fn(&self) -> bool {
|
||||
matches!(self.kind, ty::AssocKind::Fn { .. })
|
||||
}
|
||||
|
||||
pub fn is_method(&self) -> bool {
|
||||
matches!(self.kind, ty::AssocKind::Fn { has_self: true, .. })
|
||||
}
|
||||
|
||||
pub fn as_tag(&self) -> AssocTag {
|
||||
match self.kind {
|
||||
AssocKind::Const { .. } => AssocTag::Const,
|
||||
AssocKind::Fn { .. } => AssocTag::Fn,
|
||||
AssocKind::Type { .. } => AssocTag::Type,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_impl_trait_in_trait(&self) -> bool {
|
||||
self.opt_rpitit_info.is_some()
|
||||
matches!(self.kind, AssocKind::Type { data: AssocTypeData::Rpitit(_) })
|
||||
}
|
||||
|
||||
/// Returns true if:
|
||||
|
@ -114,7 +150,7 @@ impl AssocItem {
|
|||
/// - If it is in a trait impl, the item from the original trait has this attribute, or
|
||||
/// - It is an inherent assoc const.
|
||||
pub fn is_type_const_capable(&self, tcx: TyCtxt<'_>) -> bool {
|
||||
if self.kind != ty::AssocKind::Const {
|
||||
if !matches!(self.kind, ty::AssocKind::Const { .. }) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -128,26 +164,35 @@ impl AssocItem {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash, Encodable, Decodable)]
|
||||
pub enum AssocTypeData {
|
||||
Normal(Symbol),
|
||||
/// The associated type comes from an RPITIT. It has no name, and the
|
||||
/// `ImplTraitInTraitData` provides additional information about its
|
||||
/// source.
|
||||
Rpitit(ty::ImplTraitInTraitData),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash, Encodable, Decodable)]
|
||||
pub enum AssocKind {
|
||||
Const,
|
||||
Fn,
|
||||
Type,
|
||||
Const { name: Symbol },
|
||||
Fn { name: Symbol, has_self: bool },
|
||||
Type { data: AssocTypeData },
|
||||
}
|
||||
|
||||
impl AssocKind {
|
||||
pub fn namespace(&self) -> Namespace {
|
||||
match *self {
|
||||
ty::AssocKind::Type => Namespace::TypeNS,
|
||||
ty::AssocKind::Const | ty::AssocKind::Fn => Namespace::ValueNS,
|
||||
ty::AssocKind::Type { .. } => Namespace::TypeNS,
|
||||
ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => Namespace::ValueNS,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_def_kind(&self) -> DefKind {
|
||||
match self {
|
||||
AssocKind::Const => DefKind::AssocConst,
|
||||
AssocKind::Fn => DefKind::AssocFn,
|
||||
AssocKind::Type => DefKind::AssocTy,
|
||||
AssocKind::Const { .. } => DefKind::AssocConst,
|
||||
AssocKind::Fn { .. } => DefKind::AssocFn,
|
||||
AssocKind::Type { .. } => DefKind::AssocTy,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -155,15 +200,22 @@ impl AssocKind {
|
|||
impl std::fmt::Display for AssocKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
// FIXME: fails to distinguish between "associated function" and
|
||||
// "method" because `has_self` isn't known here.
|
||||
AssocKind::Fn => write!(f, "method"),
|
||||
AssocKind::Const => write!(f, "associated const"),
|
||||
AssocKind::Type => write!(f, "associated type"),
|
||||
AssocKind::Fn { has_self: true, .. } => write!(f, "method"),
|
||||
AssocKind::Fn { has_self: false, .. } => write!(f, "associated function"),
|
||||
AssocKind::Const { .. } => write!(f, "associated const"),
|
||||
AssocKind::Type { .. } => write!(f, "associated type"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Like `AssocKind`, but just the tag, no fields. Used in various kinds of matching.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum AssocTag {
|
||||
Const,
|
||||
Fn,
|
||||
Type,
|
||||
}
|
||||
|
||||
/// A list of `ty::AssocItem`s in definition order that allows for efficient lookup by name.
|
||||
///
|
||||
/// When doing lookup by name, we try to postpone hygienic comparison for as long as possible since
|
||||
|
@ -171,17 +223,17 @@ impl std::fmt::Display for AssocKind {
|
|||
/// done only on items with the same name.
|
||||
#[derive(Debug, Clone, PartialEq, HashStable)]
|
||||
pub struct AssocItems {
|
||||
items: SortedIndexMultiMap<u32, Symbol, ty::AssocItem>,
|
||||
items: SortedIndexMultiMap<u32, Option<Symbol>, ty::AssocItem>,
|
||||
}
|
||||
|
||||
impl AssocItems {
|
||||
/// Constructs an `AssociatedItems` map from a series of `ty::AssocItem`s in definition order.
|
||||
pub fn new(items_in_def_order: impl IntoIterator<Item = ty::AssocItem>) -> Self {
|
||||
let items = items_in_def_order.into_iter().map(|item| (item.name, item)).collect();
|
||||
let items = items_in_def_order.into_iter().map(|item| (item.opt_name(), item)).collect();
|
||||
AssocItems { items }
|
||||
}
|
||||
|
||||
/// Returns a slice of associated items in the order they were defined.
|
||||
/// Returns an iterator over associated items in the order they were defined.
|
||||
///
|
||||
/// New code should avoid relying on definition order. If you need a particular associated item
|
||||
/// for a known trait, make that trait a lang item instead of indexing this array.
|
||||
|
@ -198,7 +250,8 @@ impl AssocItems {
|
|||
&self,
|
||||
name: Symbol,
|
||||
) -> impl '_ + Iterator<Item = &ty::AssocItem> {
|
||||
self.items.get_by_key(name)
|
||||
assert!(!name.is_empty());
|
||||
self.items.get_by_key(Some(name))
|
||||
}
|
||||
|
||||
/// Returns the associated item with the given identifier and `AssocKind`, if one exists.
|
||||
|
@ -207,27 +260,14 @@ impl AssocItems {
|
|||
&self,
|
||||
tcx: TyCtxt<'_>,
|
||||
ident: Ident,
|
||||
kind: AssocKind,
|
||||
assoc_tag: AssocTag,
|
||||
parent_def_id: DefId,
|
||||
) -> Option<&ty::AssocItem> {
|
||||
self.filter_by_name_unhygienic(ident.name)
|
||||
.filter(|item| item.kind == kind)
|
||||
.filter(|item| item.as_tag() == assoc_tag)
|
||||
.find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id))
|
||||
}
|
||||
|
||||
/// Returns the associated item with the given identifier and any of `AssocKind`, if one
|
||||
/// exists. The identifier is matched hygienically.
|
||||
pub fn find_by_ident_and_kinds(
|
||||
&self,
|
||||
tcx: TyCtxt<'_>,
|
||||
ident: Ident,
|
||||
// Sorted in order of what kinds to look at
|
||||
kinds: &[AssocKind],
|
||||
parent_def_id: DefId,
|
||||
) -> Option<&ty::AssocItem> {
|
||||
kinds.iter().find_map(|kind| self.find_by_ident_and_kind(tcx, ident, *kind, parent_def_id))
|
||||
}
|
||||
|
||||
/// Returns the associated item with the given identifier in the given `Namespace`, if one
|
||||
/// exists. The identifier is matched hygienically.
|
||||
pub fn find_by_ident_and_namespace(
|
||||
|
@ -238,7 +278,7 @@ impl AssocItems {
|
|||
parent_def_id: DefId,
|
||||
) -> Option<&ty::AssocItem> {
|
||||
self.filter_by_name_unhygienic(ident.name)
|
||||
.filter(|item| item.kind.namespace() == ns)
|
||||
.filter(|item| item.namespace() == ns)
|
||||
.find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -464,7 +464,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
fn associated_type_def_ids(self, def_id: DefId) -> impl IntoIterator<Item = DefId> {
|
||||
self.associated_items(def_id)
|
||||
.in_definition_order()
|
||||
.filter(|assoc_item| matches!(assoc_item.kind, ty::AssocKind::Type))
|
||||
.filter(|assoc_item| assoc_item.is_type())
|
||||
.map(|assoc_item| assoc_item.def_id)
|
||||
}
|
||||
|
||||
|
@ -2147,7 +2147,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
return vec![];
|
||||
};
|
||||
|
||||
let mut v = TraitObjectVisitor(vec![], self.hir());
|
||||
let mut v = TraitObjectVisitor(vec![]);
|
||||
v.visit_ty_unambig(hir_output);
|
||||
v.0
|
||||
}
|
||||
|
@ -2160,7 +2160,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
scope_def_id: LocalDefId,
|
||||
) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span, Option<Span>)> {
|
||||
let hir_id = self.local_def_id_to_hir_id(scope_def_id);
|
||||
let mut v = TraitObjectVisitor(vec![], self.hir());
|
||||
let mut v = TraitObjectVisitor(vec![]);
|
||||
// when the return type is a type alias
|
||||
if let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir_fn_decl_by_hir_id(hir_id)
|
||||
&& let hir::TyKind::Path(hir::QPath::Resolved(
|
||||
|
|
|
@ -571,7 +571,7 @@ pub fn suggest_constraining_type_params<'a>(
|
|||
}
|
||||
|
||||
/// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for.
|
||||
pub struct TraitObjectVisitor<'tcx>(pub Vec<&'tcx hir::Ty<'tcx>>, pub crate::hir::map::Map<'tcx>);
|
||||
pub(crate) struct TraitObjectVisitor<'tcx>(pub(crate) Vec<&'tcx hir::Ty<'tcx>>);
|
||||
|
||||
impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
|
||||
fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
|
||||
|
@ -592,18 +592,6 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for.
|
||||
pub struct StaticLifetimeVisitor<'tcx>(pub Vec<Span>, pub crate::hir::map::Map<'tcx>);
|
||||
|
||||
impl<'v> hir::intravisit::Visitor<'v> for StaticLifetimeVisitor<'v> {
|
||||
fn visit_lifetime(&mut self, lt: &'v hir::Lifetime) {
|
||||
if let hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static = lt.res
|
||||
{
|
||||
self.0.push(lt.ident.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IsSuggestableVisitor<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
infer_suggestable: bool,
|
||||
|
|
|
@ -746,7 +746,7 @@ impl<'tcx> Instance<'tcx> {
|
|||
let call_once = tcx
|
||||
.associated_items(fn_once)
|
||||
.in_definition_order()
|
||||
.find(|it| it.kind == ty::AssocKind::Fn)
|
||||
.find(|it| it.is_fn())
|
||||
.unwrap()
|
||||
.def_id;
|
||||
let track_caller =
|
||||
|
|
|
@ -1462,7 +1462,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
pub fn provided_trait_methods(self, id: DefId) -> impl 'tcx + Iterator<Item = &'tcx AssocItem> {
|
||||
self.associated_items(id)
|
||||
.in_definition_order()
|
||||
.filter(move |item| item.kind == AssocKind::Fn && item.defaultness(self).has_value())
|
||||
.filter(move |item| item.is_fn() && item.defaultness(self).has_value())
|
||||
}
|
||||
|
||||
pub fn repr_options_of_def(self, did: LocalDefId) -> ReprOptions {
|
||||
|
@ -1608,8 +1608,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// return-position `impl Trait` from a trait, then provide the source info
|
||||
/// about where that RPITIT came from.
|
||||
pub fn opt_rpitit_info(self, def_id: DefId) -> Option<ImplTraitInTraitData> {
|
||||
if let DefKind::AssocTy = self.def_kind(def_id) {
|
||||
self.associated_item(def_id).opt_rpitit_info
|
||||
if let DefKind::AssocTy = self.def_kind(def_id)
|
||||
&& let AssocKind::Type { data: AssocTypeData::Rpitit(rpitit_info) } =
|
||||
self.associated_item(def_id).kind
|
||||
{
|
||||
Some(rpitit_info)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -1214,7 +1214,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
&& assoc
|
||||
.trait_container(tcx)
|
||||
.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Coroutine))
|
||||
&& assoc.name == rustc_span::sym::Return
|
||||
&& assoc.opt_name() == Some(rustc_span::sym::Return)
|
||||
{
|
||||
if let ty::Coroutine(_, args) = args.type_at(0).kind() {
|
||||
let return_ty = args.as_coroutine().return_ty();
|
||||
|
@ -1237,7 +1237,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
p!(", ");
|
||||
}
|
||||
|
||||
p!(write("{} = ", tcx.associated_item(assoc_item_def_id).name));
|
||||
p!(write("{} = ", tcx.associated_item(assoc_item_def_id).name()));
|
||||
|
||||
match term.unpack() {
|
||||
TermKind::Ty(ty) => p!(print(ty)),
|
||||
|
@ -3291,7 +3291,7 @@ define_print! {
|
|||
}
|
||||
|
||||
ty::ExistentialProjection<'tcx> {
|
||||
let name = cx.tcx().associated_item(self.def_id).name;
|
||||
let name = cx.tcx().associated_item(self.def_id).name();
|
||||
// The args don't contain the self ty (as it has been erased) but the corresp.
|
||||
// generics do as the trait always has a self ty param. We need to offset.
|
||||
let args = &self.args[cx.tcx().generics_of(self.def_id).parent_count - 1..];
|
||||
|
|
|
@ -735,7 +735,7 @@ impl<'tcx> Ty<'tcx> {
|
|||
.map(|principal| {
|
||||
tcx.associated_items(principal.def_id())
|
||||
.in_definition_order()
|
||||
.filter(|item| item.kind == ty::AssocKind::Type)
|
||||
.filter(|item| item.is_type())
|
||||
.filter(|item| !item.is_impl_trait_in_trait())
|
||||
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
|
||||
.count()
|
||||
|
|
|
@ -819,7 +819,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// Get an English description for the item's kind.
|
||||
pub fn def_kind_descr(self, def_kind: DefKind, def_id: DefId) -> &'static str {
|
||||
match def_kind {
|
||||
DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "method",
|
||||
DefKind::AssocFn if self.associated_item(def_id).is_method() => "method",
|
||||
DefKind::Closure if let Some(coroutine_kind) = self.coroutine_kind(def_id) => {
|
||||
match coroutine_kind {
|
||||
hir::CoroutineKind::Desugared(
|
||||
|
@ -873,7 +873,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// Gets an English article for the [`TyCtxt::def_kind_descr`].
|
||||
pub fn def_kind_descr_article(self, def_kind: DefKind, def_id: DefId) -> &'static str {
|
||||
match def_kind {
|
||||
DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "a",
|
||||
DefKind::AssocFn if self.associated_item(def_id).is_method() => "a",
|
||||
DefKind::Closure if let Some(coroutine_kind) = self.coroutine_kind(def_id) => {
|
||||
match coroutine_kind {
|
||||
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, ..) => "an",
|
||||
|
|
|
@ -140,8 +140,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
let success_block = target_block(TestBranch::Success);
|
||||
let fail_block = target_block(TestBranch::Failure);
|
||||
|
||||
let expect_ty = value.ty();
|
||||
let expect = self.literal_operand(test.span, value);
|
||||
let mut expect_ty = value.ty();
|
||||
let mut expect = self.literal_operand(test.span, value);
|
||||
|
||||
let mut place = place;
|
||||
let mut block = block;
|
||||
|
@ -174,6 +174,31 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
place = ref_str;
|
||||
ty = ref_str_ty;
|
||||
}
|
||||
&ty::Pat(base, _) => {
|
||||
assert_eq!(ty, value.ty());
|
||||
assert!(base.is_trivially_pure_clone_copy());
|
||||
|
||||
let transmuted_place = self.temp(base, test.span);
|
||||
self.cfg.push_assign(
|
||||
block,
|
||||
self.source_info(scrutinee_span),
|
||||
transmuted_place,
|
||||
Rvalue::Cast(CastKind::Transmute, Operand::Copy(place), base),
|
||||
);
|
||||
|
||||
let transmuted_expect = self.temp(base, test.span);
|
||||
self.cfg.push_assign(
|
||||
block,
|
||||
self.source_info(test.span),
|
||||
transmuted_expect,
|
||||
Rvalue::Cast(CastKind::Transmute, expect, base),
|
||||
);
|
||||
|
||||
place = transmuted_place;
|
||||
expect = Operand::Copy(transmuted_expect);
|
||||
ty = base;
|
||||
expect_ty = base;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
@ -715,7 +740,7 @@ fn trait_method<'tcx>(
|
|||
let item = tcx
|
||||
.associated_items(trait_def_id)
|
||||
.filter_by_name_unhygienic(method_name)
|
||||
.find(|item| item.kind == ty::AssocKind::Fn)
|
||||
.find(|item| item.is_fn())
|
||||
.expect("trait method not found");
|
||||
|
||||
let method_ty = Ty::new_fn_def(tcx, item.def_id, args);
|
||||
|
|
|
@ -42,7 +42,7 @@ impl<'a, 'tcx> UndefinedTransmutesChecker<'a, 'tcx> {
|
|||
if self.tcx.is_const_fn(def_id)
|
||||
|| matches!(
|
||||
self.tcx.opt_associated_item(def_id),
|
||||
Some(AssocItem { kind: AssocKind::Const, .. })
|
||||
Some(AssocItem { kind: AssocKind::Const { .. }, .. })
|
||||
)
|
||||
{
|
||||
let fn_sig = function.ty(self.body, self.tcx).fn_sig(self.tcx).skip_binder();
|
||||
|
|
|
@ -66,7 +66,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<
|
|||
let call_mut = tcx
|
||||
.associated_items(fn_mut)
|
||||
.in_definition_order()
|
||||
.find(|it| it.kind == ty::AssocKind::Fn)
|
||||
.find(|it| it.is_fn())
|
||||
.unwrap()
|
||||
.def_id;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ use rustc_data_structures::fx::FxIndexSet;
|
|||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::mir::visit::Visitor as MirVisitor;
|
||||
use rustc_middle::mir::{self, Location, traversal};
|
||||
use rustc_middle::ty::{self, AssocKind, Instance, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_middle::ty::{self, AssocTag, Instance, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_session::Limit;
|
||||
use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
|
||||
use rustc_span::source_map::Spanned;
|
||||
|
@ -194,7 +194,7 @@ fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) ->
|
|||
if let Some(new) = tcx.associated_items(impl_def_id).find_by_ident_and_kind(
|
||||
tcx,
|
||||
fn_ident,
|
||||
AssocKind::Fn,
|
||||
AssocTag::Fn,
|
||||
def_id,
|
||||
) {
|
||||
return Some(new.def_id);
|
||||
|
|
|
@ -792,37 +792,46 @@ where
|
|||
};
|
||||
|
||||
match proven_via {
|
||||
// Even when a trait bound has been proven using a where-bound, we
|
||||
// still need to consider alias-bounds for normalization, see
|
||||
// tests/ui/next-solver/alias-bound-shadowed-by-env.rs.
|
||||
//
|
||||
// FIXME(const_trait_impl): should this behavior also be used by
|
||||
// constness checking. Doing so is *at least theoretically* breaking,
|
||||
// see github.com/rust-lang/rust/issues/133044#issuecomment-2500709754
|
||||
TraitGoalProvenVia::ParamEnv | TraitGoalProvenVia::AliasBound => {
|
||||
let mut candidates_from_env_and_bounds: Vec<_> = candidates
|
||||
.iter()
|
||||
.filter(|c| {
|
||||
matches!(
|
||||
c.source,
|
||||
CandidateSource::AliasBound | CandidateSource::ParamEnv(_)
|
||||
)
|
||||
})
|
||||
.map(|c| c.result)
|
||||
.collect();
|
||||
let mut considered_candidates = Vec::new();
|
||||
considered_candidates.extend(
|
||||
candidates
|
||||
.iter()
|
||||
.filter(|c| matches!(c.source, CandidateSource::ParamEnv(_)))
|
||||
.map(|c| c.result),
|
||||
);
|
||||
|
||||
// Even when a trait bound has been proven using a where-bound, we
|
||||
// still need to consider alias-bounds for normalization, see
|
||||
// tests/ui/next-solver/alias-bound-shadowed-by-env.rs.
|
||||
//
|
||||
// We still need to prefer where-bounds over alias-bounds however.
|
||||
// See tests/ui/winnowing/norm-where-bound-gt-alias-bound.rs.
|
||||
//
|
||||
// FIXME(const_trait_impl): should this behavior also be used by
|
||||
// constness checking. Doing so is *at least theoretically* breaking,
|
||||
// see github.com/rust-lang/rust/issues/133044#issuecomment-2500709754
|
||||
if considered_candidates.is_empty() {
|
||||
considered_candidates.extend(
|
||||
candidates
|
||||
.iter()
|
||||
.filter(|c| matches!(c.source, CandidateSource::AliasBound))
|
||||
.map(|c| c.result),
|
||||
);
|
||||
}
|
||||
|
||||
// If the trait goal has been proven by using the environment, we want to treat
|
||||
// aliases as rigid if there are no applicable projection bounds in the environment.
|
||||
if candidates_from_env_and_bounds.is_empty() {
|
||||
if considered_candidates.is_empty() {
|
||||
if let Ok(response) = inject_normalize_to_rigid_candidate(self) {
|
||||
candidates_from_env_and_bounds.push(response);
|
||||
considered_candidates.push(response);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(response) = self.try_merge_responses(&candidates_from_env_and_bounds) {
|
||||
if let Some(response) = self.try_merge_responses(&considered_candidates) {
|
||||
Ok(response)
|
||||
} else {
|
||||
self.flounder(&candidates_from_env_and_bounds)
|
||||
self.flounder(&considered_candidates)
|
||||
}
|
||||
}
|
||||
TraitGoalProvenVia::Misc => {
|
||||
|
|
|
@ -164,6 +164,7 @@ where
|
|||
ecx: &mut EvalCtxt<'_, D>,
|
||||
goal: Goal<I, Self>,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
let cx = ecx.cx();
|
||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
@ -174,20 +175,37 @@ where
|
|||
|
||||
// Only consider auto impls of unsafe traits when there are no unsafe
|
||||
// fields.
|
||||
if ecx.cx().trait_is_unsafe(goal.predicate.def_id())
|
||||
if cx.trait_is_unsafe(goal.predicate.def_id())
|
||||
&& goal.predicate.self_ty().has_unsafe_fields()
|
||||
{
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
// We only look into opaque types during analysis for opaque types
|
||||
// outside of their defining scope. Doing so for opaques in the
|
||||
// defining scope may require calling `typeck` on the same item we're
|
||||
// currently type checking, which will result in a fatal cycle that
|
||||
// ideally we want to avoid, since we can make progress on this goal
|
||||
// via an alias bound or a locally-inferred hidden type instead.
|
||||
// We leak the implemented auto traits of opaques outside of their defining scope.
|
||||
// This depends on `typeck` of the defining scope of that opaque, which may result in
|
||||
// fatal query cycles.
|
||||
//
|
||||
// We only get to this point if we're outside of the defining scope as we'd otherwise
|
||||
// be able to normalize the opaque type. We may also cycle in case `typeck` of a defining
|
||||
// scope relies on the current context, e.g. either because it also leaks auto trait
|
||||
// bounds of opaques defined in the current context or by evaluating the current item.
|
||||
//
|
||||
// To avoid this we don't try to leak auto trait bounds if they can also be proven via
|
||||
// item bounds of the opaque. These bounds are always applicable as auto traits must not
|
||||
// have any generic parameters. They would also get preferred over the impl candidate
|
||||
// when merging candidates anyways.
|
||||
//
|
||||
// See tests/ui/impl-trait/auto-trait-leakage/avoid-query-cycle-via-item-bound.rs.
|
||||
if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() {
|
||||
debug_assert!(ecx.opaque_type_is_rigid(opaque_ty.def_id));
|
||||
for item_bound in cx.item_self_bounds(opaque_ty.def_id).skip_binder() {
|
||||
if item_bound
|
||||
.as_trait_clause()
|
||||
.is_some_and(|b| b.def_id() == goal.predicate.def_id())
|
||||
{
|
||||
return Err(NoSolution);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ecx.probe_and_evaluate_goal_for_constituent_tys(
|
||||
|
@ -1238,10 +1256,11 @@ where
|
|||
D: SolverDelegate<Interner = I>,
|
||||
I: Interner,
|
||||
{
|
||||
#[instrument(level = "debug", skip(self, goal), ret)]
|
||||
pub(super) fn merge_trait_candidates(
|
||||
&mut self,
|
||||
goal: Goal<I, TraitPredicate<I>>,
|
||||
candidates: Vec<Candidate<I>>,
|
||||
mut candidates: Vec<Candidate<I>>,
|
||||
) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
|
||||
if let TypingMode::Coherence = self.typing_mode() {
|
||||
let all_candidates: Vec<_> = candidates.into_iter().map(|c| c.result).collect();
|
||||
|
@ -1323,13 +1342,16 @@ where
|
|||
|
||||
// If there are *only* global where bounds, then make sure to return that this
|
||||
// is still reported as being proven-via the param-env so that rigid projections
|
||||
// operate correctly.
|
||||
// operate correctly. Otherwise, drop all global where-bounds before merging the
|
||||
// remaining candidates.
|
||||
let proven_via =
|
||||
if candidates.iter().all(|c| matches!(c.source, CandidateSource::ParamEnv(_))) {
|
||||
TraitGoalProvenVia::ParamEnv
|
||||
} else {
|
||||
candidates.retain(|c| !matches!(c.source, CandidateSource::ParamEnv(_)));
|
||||
TraitGoalProvenVia::Misc
|
||||
};
|
||||
|
||||
let all_candidates: Vec<_> = candidates.into_iter().map(|c| c.result).collect();
|
||||
if let Some(response) = self.try_merge_responses(&all_candidates) {
|
||||
Ok((response, Some(proven_via)))
|
||||
|
|
|
@ -1994,7 +1994,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
.iter()
|
||||
.flat_map(|i| self.r.tcx.associated_items(i).in_definition_order())
|
||||
// Only assoc fn with no receivers.
|
||||
.filter(|item| matches!(item.kind, ty::AssocKind::Fn) && !item.fn_has_self_parameter)
|
||||
.filter(|item| item.is_fn() && !item.is_method())
|
||||
.filter_map(|item| {
|
||||
// Only assoc fns that return `Self`
|
||||
let fn_sig = self.r.tcx.fn_sig(item.def_id).skip_binder();
|
||||
|
@ -2007,8 +2007,9 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
if def.did() != def_id {
|
||||
return None;
|
||||
}
|
||||
let order = !item.name.as_str().starts_with("new");
|
||||
Some((order, item.name, input_len))
|
||||
let name = item.name();
|
||||
let order = !name.as_str().starts_with("new");
|
||||
Some((order, name, input_len))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
items.sort_by_key(|(order, _, _)| *order);
|
||||
|
|
|
@ -240,7 +240,7 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc
|
|||
.flat_map(|super_poly_trait_ref| {
|
||||
tcx.associated_items(super_poly_trait_ref.def_id())
|
||||
.in_definition_order()
|
||||
.filter(|item| item.kind == ty::AssocKind::Type)
|
||||
.filter(|item| item.is_type())
|
||||
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
|
||||
.map(move |assoc_ty| {
|
||||
super_poly_trait_ref.map_bound(|super_trait_ref| {
|
||||
|
@ -446,7 +446,7 @@ pub(crate) fn transform_instance<'tcx>(
|
|||
let call = tcx
|
||||
.associated_items(trait_id)
|
||||
.in_definition_order()
|
||||
.find(|it| it.kind == ty::AssocKind::Fn)
|
||||
.find(|it| it.is_fn())
|
||||
.expect("No call-family function on closure-like Fn trait?")
|
||||
.def_id;
|
||||
|
||||
|
|
|
@ -894,12 +894,21 @@ impl<'tcx> Stable<'tcx> for rustc_session::cstore::ForeignModule {
|
|||
impl<'tcx> Stable<'tcx> for ty::AssocKind {
|
||||
type T = stable_mir::ty::AssocKind;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
|
||||
use stable_mir::ty::AssocKind;
|
||||
match self {
|
||||
ty::AssocKind::Const => AssocKind::Const,
|
||||
ty::AssocKind::Fn => AssocKind::Fn,
|
||||
ty::AssocKind::Type => AssocKind::Type,
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
use stable_mir::ty::{AssocKind, AssocTypeData};
|
||||
match *self {
|
||||
ty::AssocKind::Const { name } => AssocKind::Const { name: name.to_string() },
|
||||
ty::AssocKind::Fn { name, has_self } => {
|
||||
AssocKind::Fn { name: name.to_string(), has_self }
|
||||
}
|
||||
ty::AssocKind::Type { data } => AssocKind::Type {
|
||||
data: match data {
|
||||
ty::AssocTypeData::Normal(name) => AssocTypeData::Normal(name.to_string()),
|
||||
ty::AssocTypeData::Rpitit(rpitit) => {
|
||||
AssocTypeData::Rpitit(rpitit.stable(tables))
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -922,12 +931,9 @@ impl<'tcx> Stable<'tcx> for ty::AssocItem {
|
|||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
stable_mir::ty::AssocItem {
|
||||
def_id: tables.assoc_def(self.def_id),
|
||||
name: self.name.to_string(),
|
||||
kind: self.kind.stable(tables),
|
||||
container: self.container.stable(tables),
|
||||
trait_item_def_id: self.trait_item_def_id.map(|did| tables.assoc_def(did)),
|
||||
fn_has_self_parameter: self.fn_has_self_parameter,
|
||||
opt_rpitit_info: self.opt_rpitit_info.map(|rpitit| rpitit.stable(tables)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,9 +22,10 @@ impl Display for Ty {
|
|||
impl Display for AssocKind {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
AssocKind::Fn => write!(f, "method"),
|
||||
AssocKind::Const => write!(f, "associated const"),
|
||||
AssocKind::Type => write!(f, "associated type"),
|
||||
AssocKind::Fn { has_self: true, .. } => write!(f, "method"),
|
||||
AssocKind::Fn { has_self: false, .. } => write!(f, "associated function"),
|
||||
AssocKind::Const { .. } => write!(f, "associated const"),
|
||||
AssocKind::Type { .. } => write!(f, "associated type"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1578,29 +1578,28 @@ crate_def! {
|
|||
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
||||
pub struct AssocItem {
|
||||
pub def_id: AssocDef,
|
||||
pub name: Symbol,
|
||||
pub kind: AssocKind,
|
||||
pub container: AssocItemContainer,
|
||||
|
||||
/// If this is an item in an impl of a trait then this is the `DefId` of
|
||||
/// the associated item on the trait that this implements.
|
||||
pub trait_item_def_id: Option<AssocDef>,
|
||||
}
|
||||
|
||||
/// Whether this is a method with an explicit self
|
||||
/// as its first parameter, allowing method calls.
|
||||
pub fn_has_self_parameter: bool,
|
||||
|
||||
/// `Some` if the associated item (an associated type) comes from the
|
||||
/// return-position `impl Trait` in trait desugaring. The `ImplTraitInTraitData`
|
||||
/// provides additional information about its source.
|
||||
pub opt_rpitit_info: Option<ImplTraitInTraitData>,
|
||||
#[derive(Clone, PartialEq, Debug, Eq, Serialize)]
|
||||
pub enum AssocTypeData {
|
||||
Normal(Symbol),
|
||||
/// The associated type comes from an RPITIT. It has no name, and the
|
||||
/// `ImplTraitInTraitData` provides additional information about its
|
||||
/// source.
|
||||
Rpitit(ImplTraitInTraitData),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
||||
pub enum AssocKind {
|
||||
Const,
|
||||
Fn,
|
||||
Type,
|
||||
Const { name: Symbol },
|
||||
Fn { name: Symbol, has_self: bool },
|
||||
Type { data: AssocTypeData },
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
||||
|
@ -1617,6 +1616,6 @@ pub enum ImplTraitInTraitData {
|
|||
|
||||
impl AssocItem {
|
||||
pub fn is_impl_trait_in_trait(&self) -> bool {
|
||||
self.opt_rpitit_info.is_some()
|
||||
matches!(self.kind, AssocKind::Type { data: AssocTypeData::Rpitit(_) })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -615,7 +615,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
|||
cx.print_def_path(trait_ref.def_id, trait_ref.args)?;
|
||||
}
|
||||
ty::ExistentialPredicate::Projection(projection) => {
|
||||
let name = cx.tcx.associated_item(projection.def_id).name;
|
||||
let name = cx.tcx.associated_item(projection.def_id).name();
|
||||
cx.push("p");
|
||||
cx.push_ident(name.as_str());
|
||||
match projection.term.unpack() {
|
||||
|
|
|
@ -2334,13 +2334,13 @@ impl<'tcx> ObligationCause<'tcx> {
|
|||
subdiags: Vec<TypeErrorAdditionalDiags>,
|
||||
) -> ObligationCauseFailureCode {
|
||||
match self.code() {
|
||||
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn, .. } => {
|
||||
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn { .. }, .. } => {
|
||||
ObligationCauseFailureCode::MethodCompat { span, subdiags }
|
||||
}
|
||||
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => {
|
||||
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type { .. }, .. } => {
|
||||
ObligationCauseFailureCode::TypeCompat { span, subdiags }
|
||||
}
|
||||
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const, .. } => {
|
||||
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const { .. }, .. } => {
|
||||
ObligationCauseFailureCode::ConstCompat { span, subdiags }
|
||||
}
|
||||
ObligationCauseCode::BlockTailExpression(.., hir::MatchSource::TryDesugar(_)) => {
|
||||
|
@ -2398,13 +2398,13 @@ impl<'tcx> ObligationCause<'tcx> {
|
|||
|
||||
fn as_requirement_str(&self) -> &'static str {
|
||||
match self.code() {
|
||||
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn, .. } => {
|
||||
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn { .. }, .. } => {
|
||||
"method type is compatible with trait"
|
||||
}
|
||||
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => {
|
||||
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type { .. }, .. } => {
|
||||
"associated type is compatible with trait"
|
||||
}
|
||||
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const, .. } => {
|
||||
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const { .. }, .. } => {
|
||||
"const is compatible with trait"
|
||||
}
|
||||
ObligationCauseCode::MainFunctionType => "`main` function has the correct type",
|
||||
|
@ -2422,9 +2422,13 @@ pub struct ObligationCauseAsDiagArg<'tcx>(pub ObligationCause<'tcx>);
|
|||
impl IntoDiagArg for ObligationCauseAsDiagArg<'_> {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
|
||||
let kind = match self.0.code() {
|
||||
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn, .. } => "method_compat",
|
||||
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => "type_compat",
|
||||
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const, .. } => {
|
||||
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn { .. }, .. } => {
|
||||
"method_compat"
|
||||
}
|
||||
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type { .. }, .. } => {
|
||||
"type_compat"
|
||||
}
|
||||
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const { .. }, .. } => {
|
||||
"const_compat"
|
||||
}
|
||||
ObligationCauseCode::MainFunctionType => "fn_main_correct_type",
|
||||
|
|
|
@ -98,7 +98,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
let assoc_item = self.tcx().associated_item(trait_item_def_id);
|
||||
let mut visitor = TypeParamSpanVisitor { tcx: self.tcx(), types: vec![] };
|
||||
match assoc_item.kind {
|
||||
ty::AssocKind::Fn => {
|
||||
ty::AssocKind::Fn { .. } => {
|
||||
if let Some(hir_id) =
|
||||
assoc_item.def_id.as_local().map(|id| self.tcx().local_def_id_to_hir_id(id))
|
||||
{
|
||||
|
|
|
@ -158,6 +158,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
&& self
|
||||
.tcx()
|
||||
.opt_associated_item(scope_def_id.to_def_id())
|
||||
.is_some_and(|i| i.fn_has_self_parameter)
|
||||
.is_some_and(|i| i.is_method())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -782,8 +782,8 @@ fn foo(&self) -> Self::T { String::new() }
|
|||
let methods: Vec<(Span, String)> = items
|
||||
.in_definition_order()
|
||||
.filter(|item| {
|
||||
ty::AssocKind::Fn == item.kind
|
||||
&& Some(item.name) != current_method_ident
|
||||
item.is_fn()
|
||||
&& Some(item.name()) != current_method_ident
|
||||
&& !tcx.is_doc_hidden(item.def_id)
|
||||
})
|
||||
.filter_map(|item| {
|
||||
|
|
|
@ -1017,7 +1017,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
infer::BoundRegion(_, br, infer::AssocTypeProjection(def_id)) => format!(
|
||||
" for lifetime parameter {}in trait containing associated type `{}`",
|
||||
br_string(br),
|
||||
self.tcx.associated_item(def_id).name
|
||||
self.tcx.associated_item(def_id).name()
|
||||
),
|
||||
infer::RegionParameterDefinition(_, name) => {
|
||||
format!(" for lifetime parameter `{name}`")
|
||||
|
|
|
@ -348,11 +348,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
&& let None = self.tainted_by_errors()
|
||||
{
|
||||
let (verb, noun) = match self.tcx.associated_item(item_id).kind {
|
||||
ty::AssocKind::Const => ("refer to the", "constant"),
|
||||
ty::AssocKind::Fn => ("call", "function"),
|
||||
ty::AssocKind::Const { .. } => ("refer to the", "constant"),
|
||||
ty::AssocKind::Fn { .. } => ("call", "function"),
|
||||
// This is already covered by E0223, but this following single match
|
||||
// arm doesn't hurt here.
|
||||
ty::AssocKind::Type => ("refer to the", "type"),
|
||||
ty::AssocKind::Type { .. } => ("refer to the", "type"),
|
||||
};
|
||||
|
||||
// Replace the more general E0283 with a more specific error
|
||||
|
|
|
@ -2112,16 +2112,20 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
trait_ref: DefId,
|
||||
) {
|
||||
if let Some(assoc_item) = self.tcx.opt_associated_item(item_def_id) {
|
||||
if let ty::AssocKind::Const | ty::AssocKind::Type = assoc_item.kind {
|
||||
if let ty::AssocKind::Const { .. } | ty::AssocKind::Type { .. } = assoc_item.kind {
|
||||
err.note(format!(
|
||||
"{}s cannot be accessed directly on a `trait`, they can only be \
|
||||
accessed through a specific `impl`",
|
||||
self.tcx.def_kind_descr(assoc_item.kind.as_def_kind(), item_def_id)
|
||||
self.tcx.def_kind_descr(assoc_item.as_def_kind(), item_def_id)
|
||||
));
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"use the fully qualified path to an implementation",
|
||||
format!("<Type as {}>::{}", self.tcx.def_path_str(trait_ref), assoc_item.name),
|
||||
format!(
|
||||
"<Type as {}>::{}",
|
||||
self.tcx.def_path_str(trait_ref),
|
||||
assoc_item.name()
|
||||
),
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
|
@ -5411,7 +5415,7 @@ fn point_at_assoc_type_restriction<G: EmissionGuarantee>(
|
|||
tcx.associated_items(data.impl_or_alias_def_id).find_by_ident_and_kind(
|
||||
tcx,
|
||||
Ident::with_dummy_span(name),
|
||||
ty::AssocKind::Type,
|
||||
ty::AssocTag::Type,
|
||||
data.impl_or_alias_def_id,
|
||||
)
|
||||
{
|
||||
|
|
|
@ -188,7 +188,7 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span
|
|||
tcx.associated_items(trait_def_id)
|
||||
.in_definition_order()
|
||||
// We're only looking at associated type bounds
|
||||
.filter(|item| item.kind == ty::AssocKind::Type)
|
||||
.filter(|item| item.is_type())
|
||||
// Ignore GATs with `Self: Sized`
|
||||
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
|
||||
.flat_map(|item| tcx.explicit_item_bounds(item.def_id).iter_identity_copied())
|
||||
|
@ -298,31 +298,33 @@ pub fn dyn_compatibility_violations_for_assoc_item(
|
|||
match item.kind {
|
||||
// Associated consts are never dyn-compatible, as they can't have `where` bounds yet at all,
|
||||
// and associated const bounds in trait objects aren't a thing yet either.
|
||||
ty::AssocKind::Const => {
|
||||
vec![DynCompatibilityViolation::AssocConst(item.name, item.ident(tcx).span)]
|
||||
ty::AssocKind::Const { name } => {
|
||||
vec![DynCompatibilityViolation::AssocConst(name, item.ident(tcx).span)]
|
||||
}
|
||||
ty::AssocKind::Fn => virtual_call_violations_for_method(tcx, trait_def_id, item)
|
||||
.into_iter()
|
||||
.map(|v| {
|
||||
let node = tcx.hir_get_if_local(item.def_id);
|
||||
// Get an accurate span depending on the violation.
|
||||
let span = match (&v, node) {
|
||||
(MethodViolationCode::ReferencesSelfInput(Some(span)), _) => *span,
|
||||
(MethodViolationCode::UndispatchableReceiver(Some(span)), _) => *span,
|
||||
(MethodViolationCode::ReferencesImplTraitInTrait(span), _) => *span,
|
||||
(MethodViolationCode::ReferencesSelfOutput, Some(node)) => {
|
||||
node.fn_decl().map_or(item.ident(tcx).span, |decl| decl.output.span())
|
||||
}
|
||||
_ => item.ident(tcx).span,
|
||||
};
|
||||
ty::AssocKind::Fn { name, .. } => {
|
||||
virtual_call_violations_for_method(tcx, trait_def_id, item)
|
||||
.into_iter()
|
||||
.map(|v| {
|
||||
let node = tcx.hir_get_if_local(item.def_id);
|
||||
// Get an accurate span depending on the violation.
|
||||
let span = match (&v, node) {
|
||||
(MethodViolationCode::ReferencesSelfInput(Some(span)), _) => *span,
|
||||
(MethodViolationCode::UndispatchableReceiver(Some(span)), _) => *span,
|
||||
(MethodViolationCode::ReferencesImplTraitInTrait(span), _) => *span,
|
||||
(MethodViolationCode::ReferencesSelfOutput, Some(node)) => {
|
||||
node.fn_decl().map_or(item.ident(tcx).span, |decl| decl.output.span())
|
||||
}
|
||||
_ => item.ident(tcx).span,
|
||||
};
|
||||
|
||||
DynCompatibilityViolation::Method(item.name, v, span)
|
||||
})
|
||||
.collect(),
|
||||
DynCompatibilityViolation::Method(name, v, span)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
// Associated types can only be dyn-compatible if they have `Self: Sized` bounds.
|
||||
ty::AssocKind::Type => {
|
||||
ty::AssocKind::Type { .. } => {
|
||||
if !tcx.generics_of(item.def_id).is_own_empty() && !item.is_impl_trait_in_trait() {
|
||||
vec![DynCompatibilityViolation::GAT(item.name, item.ident(tcx).span)]
|
||||
vec![DynCompatibilityViolation::GAT(item.name(), item.ident(tcx).span)]
|
||||
} else {
|
||||
// We will permit associated types if they are explicitly mentioned in the trait object.
|
||||
// We can't check this here, as here we only check if it is guaranteed to not be possible.
|
||||
|
@ -344,7 +346,7 @@ fn virtual_call_violations_for_method<'tcx>(
|
|||
let sig = tcx.fn_sig(method.def_id).instantiate_identity();
|
||||
|
||||
// The method's first parameter must be named `self`
|
||||
if !method.fn_has_self_parameter {
|
||||
if !method.is_method() {
|
||||
let sugg = if let Some(hir::Node::TraitItem(hir::TraitItem {
|
||||
generics,
|
||||
kind: hir::TraitItemKind::Fn(sig, _),
|
||||
|
|
|
@ -1393,7 +1393,7 @@ fn confirm_future_candidate<'cx, 'tcx>(
|
|||
coroutine_sig,
|
||||
);
|
||||
|
||||
debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Output);
|
||||
debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name(), sym::Output);
|
||||
|
||||
let predicate = ty::ProjectionPredicate {
|
||||
projection_term: ty::AliasTerm::new_from_args(
|
||||
|
@ -1439,7 +1439,7 @@ fn confirm_iterator_candidate<'cx, 'tcx>(
|
|||
gen_sig,
|
||||
);
|
||||
|
||||
debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Item);
|
||||
debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name(), sym::Item);
|
||||
|
||||
let predicate = ty::ProjectionPredicate {
|
||||
projection_term: ty::AliasTerm::new_from_args(
|
||||
|
@ -1485,7 +1485,7 @@ fn confirm_async_iterator_candidate<'cx, 'tcx>(
|
|||
gen_sig,
|
||||
);
|
||||
|
||||
debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Item);
|
||||
debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name(), sym::Item);
|
||||
|
||||
let ty::Adt(_poll_adt, args) = *yield_ty.kind() else {
|
||||
bug!();
|
||||
|
@ -2005,7 +2005,8 @@ fn confirm_impl_candidate<'cx, 'tcx>(
|
|||
if !assoc_ty.item.defaultness(tcx).has_value() {
|
||||
debug!(
|
||||
"confirm_impl_candidate: no associated type {:?} for {:?}",
|
||||
assoc_ty.item.name, obligation.predicate
|
||||
assoc_ty.item.name(),
|
||||
obligation.predicate
|
||||
);
|
||||
if tcx.impl_self_is_guaranteed_unsized(impl_def_id) {
|
||||
// We treat this projection as rigid here, which is represented via
|
||||
|
|
|
@ -594,9 +594,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
// Associated types that require `Self: Sized` do not show up in the built-in
|
||||
// implementation of `Trait for dyn Trait`, and can be dropped here.
|
||||
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
|
||||
.filter_map(
|
||||
|item| if item.kind == ty::AssocKind::Type { Some(item.def_id) } else { None },
|
||||
)
|
||||
.filter_map(|item| if item.is_type() { Some(item.def_id) } else { None })
|
||||
.collect();
|
||||
|
||||
for assoc_type in assoc_types {
|
||||
|
|
|
@ -197,10 +197,8 @@ fn own_existential_vtable_entries_iter(
|
|||
tcx: TyCtxt<'_>,
|
||||
trait_def_id: DefId,
|
||||
) -> impl Iterator<Item = DefId> {
|
||||
let trait_methods = tcx
|
||||
.associated_items(trait_def_id)
|
||||
.in_definition_order()
|
||||
.filter(|item| item.kind == ty::AssocKind::Fn);
|
||||
let trait_methods =
|
||||
tcx.associated_items(trait_def_id).in_definition_order().filter(|item| item.is_fn());
|
||||
|
||||
// Now list each method's DefId (for within its trait).
|
||||
let own_entries = trait_methods.filter_map(move |&trait_method| {
|
||||
|
|
|
@ -6,7 +6,6 @@ use rustc_hir::{self as hir, AmbigArg};
|
|||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::kw;
|
||||
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
*providers = Providers {
|
||||
|
@ -129,39 +128,35 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AssocItem {
|
|||
|
||||
fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty::AssocItem {
|
||||
let owner_id = trait_item_ref.id.owner_id;
|
||||
let (kind, has_self) = match trait_item_ref.kind {
|
||||
hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
|
||||
hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
|
||||
hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
|
||||
let name = trait_item_ref.ident.name;
|
||||
let kind = match trait_item_ref.kind {
|
||||
hir::AssocItemKind::Const => ty::AssocKind::Const { name },
|
||||
hir::AssocItemKind::Fn { has_self } => ty::AssocKind::Fn { name, has_self },
|
||||
hir::AssocItemKind::Type => ty::AssocKind::Type { data: ty::AssocTypeData::Normal(name) },
|
||||
};
|
||||
|
||||
ty::AssocItem {
|
||||
name: trait_item_ref.ident.name,
|
||||
kind,
|
||||
def_id: owner_id.to_def_id(),
|
||||
trait_item_def_id: Some(owner_id.to_def_id()),
|
||||
container: ty::AssocItemContainer::Trait,
|
||||
fn_has_self_parameter: has_self,
|
||||
opt_rpitit_info: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::AssocItem {
|
||||
let def_id = impl_item_ref.id.owner_id;
|
||||
let (kind, has_self) = match impl_item_ref.kind {
|
||||
hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
|
||||
hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
|
||||
hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
|
||||
let name = impl_item_ref.ident.name;
|
||||
let kind = match impl_item_ref.kind {
|
||||
hir::AssocItemKind::Const => ty::AssocKind::Const { name },
|
||||
hir::AssocItemKind::Fn { has_self } => ty::AssocKind::Fn { name, has_self },
|
||||
hir::AssocItemKind::Type => ty::AssocKind::Type { data: ty::AssocTypeData::Normal(name) },
|
||||
};
|
||||
|
||||
ty::AssocItem {
|
||||
name: impl_item_ref.ident.name,
|
||||
kind,
|
||||
def_id: def_id.to_def_id(),
|
||||
trait_item_def_id: impl_item_ref.trait_item_def_id,
|
||||
container: ty::AssocItemContainer::Impl,
|
||||
fn_has_self_parameter: has_self,
|
||||
opt_rpitit_info: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -264,16 +259,15 @@ fn associated_type_for_impl_trait_in_trait(
|
|||
trait_assoc_ty.def_ident_span(Some(span));
|
||||
|
||||
trait_assoc_ty.associated_item(ty::AssocItem {
|
||||
name: kw::Empty,
|
||||
kind: ty::AssocKind::Type,
|
||||
kind: ty::AssocKind::Type {
|
||||
data: ty::AssocTypeData::Rpitit(ImplTraitInTraitData::Trait {
|
||||
fn_def_id: fn_def_id.to_def_id(),
|
||||
opaque_def_id: opaque_ty_def_id.to_def_id(),
|
||||
}),
|
||||
},
|
||||
def_id,
|
||||
trait_item_def_id: None,
|
||||
container: ty::AssocItemContainer::Trait,
|
||||
fn_has_self_parameter: false,
|
||||
opt_rpitit_info: Some(ImplTraitInTraitData::Trait {
|
||||
fn_def_id: fn_def_id.to_def_id(),
|
||||
opaque_def_id: opaque_ty_def_id.to_def_id(),
|
||||
}),
|
||||
});
|
||||
|
||||
// Copy visility of the containing function.
|
||||
|
@ -317,13 +311,14 @@ fn associated_type_for_impl_trait_in_impl(
|
|||
impl_assoc_ty.def_ident_span(Some(span));
|
||||
|
||||
impl_assoc_ty.associated_item(ty::AssocItem {
|
||||
name: kw::Empty,
|
||||
kind: ty::AssocKind::Type,
|
||||
kind: ty::AssocKind::Type {
|
||||
data: ty::AssocTypeData::Rpitit(ImplTraitInTraitData::Impl {
|
||||
fn_def_id: impl_fn_def_id.to_def_id(),
|
||||
}),
|
||||
},
|
||||
def_id,
|
||||
trait_item_def_id: Some(trait_assoc_def_id),
|
||||
container: ty::AssocItemContainer::Impl,
|
||||
fn_has_self_parameter: false,
|
||||
opt_rpitit_info: Some(ImplTraitInTraitData::Impl { fn_def_id: impl_fn_def_id.to_def_id() }),
|
||||
});
|
||||
|
||||
// Copy visility of the containing function.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue