summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis/src/astconv
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
commit9835e2ae736235810b4ea1c162ca5e65c547e770 (patch)
tree3fcebf40ed70e581d776a8a4c65923e8ec20e026 /compiler/rustc_hir_analysis/src/astconv
parentReleasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff)
downloadrustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz
rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_hir_analysis/src/astconv')
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/errors.rs16
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/generics.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs328
3 files changed, 231 insertions, 121 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index 113c3f08a..7b922f5d5 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -243,13 +243,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let note = format!("{title} is defined in an impl for the type `{impl_ty}`");
if let Some(span) = note_span {
- err.span_note(span, &note);
+ err.span_note(span, note);
} else {
- err.note(&note);
+ err.note(note);
}
}
if candidates.len() > limit {
- err.note(&format!("and {} others", candidates.len() - limit));
+ err.note(format!("and {} others", candidates.len() - limit));
}
}
@@ -303,7 +303,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
"associated type `{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!(
+ err.note(format!(
"the associated type was found for\n{type_candidates}{additional_types}",
));
add_def_label(&mut err);
@@ -390,10 +390,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let mut err = tcx.sess.struct_span_err(
name.span,
- &format!("the associated type `{name}` exists for `{self_ty}`, but its trait bounds were not satisfied")
+ format!("the associated type `{name}` exists for `{self_ty}`, but its trait bounds were not satisfied")
);
if !bounds.is_empty() {
- err.note(&format!(
+ err.note(format!(
"the following trait bounds were not satisfied:\n{}",
bounds.join("\n")
));
@@ -409,7 +409,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if !tcx.sess.source_map().is_span_accessible(span) {
continue;
}
- err.span_label(span, &msg);
+ err.span_label(span, msg);
}
add_def_label(&mut err);
err.emit()
@@ -589,7 +589,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
if !suggestions.is_empty() {
err.multipart_suggestion(
- &format!("specify the associated type{}", pluralize!(types_count)),
+ format!("specify the associated type{}", pluralize!(types_count)),
suggestions,
Applicability::HasPlaceholders,
);
diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index 3b5c67de2..39d1d1f2d 100644
--- a/compiler/rustc_hir_analysis/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -24,7 +24,7 @@ fn generic_arg_mismatch_err(
arg: &GenericArg<'_>,
param: &GenericParamDef,
possible_ordering_error: bool,
- help: Option<&str>,
+ help: Option<String>,
) -> ErrorGuaranteed {
let sess = tcx.sess;
let mut err = struct_span_err!(
@@ -112,7 +112,7 @@ fn generic_arg_mismatch_err(
if let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body.value.kind
{
if let Res::Def(DefKind::Fn { .. }, id) = path.res {
- err.help(&format!("`{}` is a function item, not a type", tcx.item_name(id)));
+ err.help(format!("`{}` is a function item, not a type", tcx.item_name(id)));
err.help("function item types cannot be named directly");
}
}
@@ -130,7 +130,7 @@ fn generic_arg_mismatch_err(
} else {
(arg.descr(), param.kind.descr())
};
- err.note(&format!("{} arguments must be provided before {} arguments", first, last));
+ err.note(format!("{} arguments must be provided before {} arguments", first, last));
if let Some(help) = help {
err.help(help);
}
@@ -300,7 +300,7 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
arg,
param,
!args_iter.clone().is_sorted_by_key(|arg| arg.to_ord()),
- Some(&format!(
+ Some(format!(
"reorder the arguments: {}: `<{}>`",
param_types_present
.into_iter()
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 8d1156c17..2c60a0624 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -19,7 +19,7 @@ use rustc_ast::TraitObjectSyntax;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, FatalError,
- MultiSpan,
+ MultiSpan, StashKey,
};
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
@@ -38,7 +38,6 @@ use rustc_middle::ty::{self, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}
use rustc_middle::ty::{DynKind, ToPredicate};
use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS};
use rustc_span::edit_distance::find_best_match_for_name;
-use rustc_span::edition::Edition;
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::{sym, Span, DUMMY_SP};
use rustc_target::spec::abi;
@@ -56,6 +55,9 @@ use std::slice;
#[derive(Debug)]
pub struct PathSeg(pub DefId, pub usize);
+#[derive(Copy, Clone, Debug)]
+pub struct OnlySelfBounds(pub bool);
+
pub trait AstConv<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx>;
@@ -447,14 +449,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
handle_ty_args(has_default, &inf.to_ty())
}
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
- ty::Const::from_opt_const_arg_anon_const(
- tcx,
- ty::WithOptConstParam {
- did: ct.value.def_id,
- const_param_did: Some(param.def_id),
- },
- )
- .into()
+ let did = ct.value.def_id;
+ tcx.feed_anon_const_type(did, tcx.type_of(param.def_id));
+ ty::Const::from_anon_const(tcx, did).into()
}
(&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => {
let ty = tcx
@@ -466,7 +463,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self.astconv.ct_infer(ty, Some(param), inf.span).into()
} else {
self.inferred_params.push(inf.span);
- tcx.const_error(ty).into()
+ tcx.const_error_misc(ty).into()
}
}
_ => unreachable!(),
@@ -520,7 +517,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.no_bound_vars()
.expect("const parameter types cannot be generic");
if let Err(guar) = ty.error_reported() {
- return tcx.const_error_with_guaranteed(ty, guar).into();
+ return tcx.const_error(ty, guar).into();
}
if !infer_args && has_default {
tcx.const_param_default(param.def_id).subst(tcx, substs.unwrap()).into()
@@ -529,7 +526,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self.astconv.ct_infer(ty, Some(param), self.span).into()
} else {
// We've already errored above about the mismatch.
- tcx.const_error(ty).into()
+ tcx.const_error_misc(ty).into()
}
}
}
@@ -667,6 +664,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
span: Span,
binding_span: Option<Span>,
constness: ty::BoundConstness,
+ polarity: ty::ImplPolarity,
bounds: &mut Bounds<'tcx>,
speculative: bool,
trait_ref_span: Span,
@@ -675,6 +673,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
args: &GenericArgs<'_>,
infer_args: bool,
self_ty: Ty<'tcx>,
+ only_self_bounds: OnlySelfBounds,
) -> GenericArgCountResult {
let (substs, arg_count) = self.create_substs_for_ast_path(
trait_ref_span,
@@ -694,13 +693,23 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let assoc_bindings = self.create_assoc_bindings_for_generic_args(args);
let poly_trait_ref =
- ty::Binder::bind_with_vars(tcx.mk_trait_ref(trait_def_id, substs), bound_vars);
+ ty::Binder::bind_with_vars(ty::TraitRef::new(tcx, trait_def_id, substs), bound_vars);
debug!(?poly_trait_ref, ?assoc_bindings);
- bounds.push_trait_bound(tcx, poly_trait_ref, span, constness);
+ bounds.push_trait_bound(tcx, poly_trait_ref, span, constness, polarity);
let mut dup_bindings = FxHashMap::default();
for binding in &assoc_bindings {
+ // Don't register additional associated type bounds for negative bounds,
+ // since we should have emitten an error for them earlier, and they will
+ // not be well-formed!
+ if polarity == ty::ImplPolarity::Negative {
+ self.tcx()
+ .sess
+ .delay_span_bug(binding.span, "negative trait bounds should not have bindings");
+ continue;
+ }
+
// Specify type to assert that error was already reported in `Err` case.
let _: Result<_, ErrorGuaranteed> = self.add_predicates_for_ast_type_binding(
hir_id,
@@ -711,6 +720,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&mut dup_bindings,
binding_span.unwrap_or(binding.span),
constness,
+ only_self_bounds,
+ polarity,
);
// Okay to ignore `Err` because of `ErrorGuaranteed` (see above).
}
@@ -743,9 +754,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
trait_ref: &hir::TraitRef<'_>,
span: Span,
constness: ty::BoundConstness,
+ polarity: ty::ImplPolarity,
self_ty: Ty<'tcx>,
bounds: &mut Bounds<'tcx>,
speculative: bool,
+ only_self_bounds: OnlySelfBounds,
) -> GenericArgCountResult {
let hir_id = trait_ref.hir_ref_id;
let binding_span = None;
@@ -763,6 +776,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
span,
binding_span,
constness,
+ polarity,
bounds,
speculative,
trait_ref_span,
@@ -771,6 +785,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
args,
infer_args,
self_ty,
+ only_self_bounds,
)
}
@@ -782,6 +797,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
args: &GenericArgs<'_>,
self_ty: Ty<'tcx>,
bounds: &mut Bounds<'tcx>,
+ only_self_bounds: OnlySelfBounds,
) {
let binding_span = Some(span);
let constness = ty::BoundConstness::NotConst;
@@ -796,6 +812,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
span,
binding_span,
constness,
+ ty::ImplPolarity::Positive,
bounds,
speculative,
trait_ref_span,
@@ -804,6 +821,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
args,
infer_args,
self_ty,
+ only_self_bounds,
);
}
@@ -827,7 +845,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if let Some(b) = trait_segment.args().bindings.first() {
prohibit_assoc_ty_binding(self.tcx(), b.span, Some((trait_segment, span)));
}
- self.tcx().mk_trait_ref(trait_def_id, substs)
+ ty::TraitRef::new(self.tcx(), trait_def_id, substs)
}
#[instrument(level = "debug", skip(self, span))]
@@ -952,28 +970,43 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
ast_bounds: I,
bounds: &mut Bounds<'tcx>,
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
+ only_self_bounds: OnlySelfBounds,
) {
for ast_bound in ast_bounds {
match ast_bound {
hir::GenericBound::Trait(poly_trait_ref, modifier) => {
- let constness = match modifier {
- hir::TraitBoundModifier::MaybeConst => ty::BoundConstness::ConstIfConst,
- hir::TraitBoundModifier::None => ty::BoundConstness::NotConst,
+ let (constness, polarity) = match modifier {
+ hir::TraitBoundModifier::MaybeConst => {
+ (ty::BoundConstness::ConstIfConst, ty::ImplPolarity::Positive)
+ }
+ hir::TraitBoundModifier::None => {
+ (ty::BoundConstness::NotConst, ty::ImplPolarity::Positive)
+ }
+ hir::TraitBoundModifier::Negative => {
+ (ty::BoundConstness::NotConst, ty::ImplPolarity::Negative)
+ }
hir::TraitBoundModifier::Maybe => continue,
};
-
let _ = self.instantiate_poly_trait_ref(
&poly_trait_ref.trait_ref,
poly_trait_ref.span,
constness,
+ polarity,
param_ty,
bounds,
false,
+ only_self_bounds,
);
}
&hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
self.instantiate_lang_item_trait_ref(
- lang_item, span, hir_id, args, param_ty, bounds,
+ lang_item,
+ span,
+ hir_id,
+ args,
+ param_ty,
+ bounds,
+ only_self_bounds,
);
}
hir::GenericBound::Outlives(lifetime) => {
@@ -1011,13 +1044,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&self,
param_ty: Ty<'tcx>,
ast_bounds: &[hir::GenericBound<'_>],
+ only_self_bounds: OnlySelfBounds,
) -> Bounds<'tcx> {
- self.compute_bounds_inner(param_ty, ast_bounds)
+ let mut bounds = Bounds::default();
+ self.add_bounds(
+ param_ty,
+ ast_bounds.iter(),
+ &mut bounds,
+ ty::List::empty(),
+ only_self_bounds,
+ );
+ debug!(?bounds);
+
+ bounds
}
/// Convert the bounds in `ast_bounds` that refer to traits which define an associated type
/// named `assoc_name` into ty::Bounds. Ignore the rest.
- pub(crate) fn compute_bounds_that_match_assoc_type(
+ pub(crate) fn compute_bounds_that_match_assoc_item(
&self,
param_ty: Ty<'tcx>,
ast_bounds: &[hir::GenericBound<'_>],
@@ -1028,23 +1072,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
for ast_bound in ast_bounds {
if let Some(trait_ref) = ast_bound.trait_ref()
&& let Some(trait_did) = trait_ref.trait_def_id()
- && self.tcx().trait_may_define_assoc_type(trait_did, assoc_name)
+ && self.tcx().trait_may_define_assoc_item(trait_did, assoc_name)
{
result.push(ast_bound.clone());
}
}
- self.compute_bounds_inner(param_ty, &result)
- }
-
- fn compute_bounds_inner(
- &self,
- param_ty: Ty<'tcx>,
- ast_bounds: &[hir::GenericBound<'_>],
- ) -> Bounds<'tcx> {
let mut bounds = Bounds::default();
-
- self.add_bounds(param_ty, ast_bounds.iter(), &mut bounds, ty::List::empty());
+ self.add_bounds(
+ param_ty,
+ result.iter(),
+ &mut bounds,
+ ty::List::empty(),
+ OnlySelfBounds(true),
+ );
debug!(?bounds);
bounds
@@ -1067,6 +1108,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
dup_bindings: &mut FxHashMap<DefId, Span>,
path_span: Span,
constness: ty::BoundConstness,
+ only_self_bounds: OnlySelfBounds,
+ polarity: ty::ImplPolarity,
) -> Result<(), ErrorGuaranteed> {
// Given something like `U: SomeTrait<T = X>`, we want to produce a
// predicate like `<U as SomeTrait>::T = X`. This is somewhat
@@ -1097,11 +1140,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
) {
trait_ref
} else {
- return Err(tcx.sess.emit_err(crate::errors::ReturnTypeNotationMissingMethod {
- span: binding.span,
- trait_name: tcx.item_name(trait_ref.def_id()),
- assoc_name: binding.item_name.name,
- }));
+ self.one_bound_for_assoc_method(
+ traits::supertraits(tcx, trait_ref),
+ trait_ref.print_only_trait_path(),
+ binding.item_name,
+ path_span,
+ )?
}
} else if self.trait_defines_associated_item_named(
trait_ref.def_id(),
@@ -1115,7 +1159,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// those that do.
self.one_bound_for_assoc_type(
|| traits::supertraits(tcx, trait_ref),
- trait_ref.print_only_trait_path(),
+ trait_ref.skip_binder().print_only_trait_name(),
binding.item_name,
path_span,
match binding.kind {
@@ -1147,9 +1191,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.sess
.struct_span_err(
binding.span,
- &format!("{} `{}` is private", assoc_item.kind, binding.item_name),
+ format!("{} `{}` is private", assoc_item.kind, binding.item_name),
)
- .span_label(binding.span, &format!("private {}", assoc_item.kind))
+ .span_label(binding.span, format!("private {}", assoc_item.kind))
.emit();
}
tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None);
@@ -1321,11 +1365,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let expected = tcx.def_descr(assoc_item_def_id);
let mut err = tcx.sess.struct_span_err(
binding.span,
- &format!("expected {expected} bound, found {got}"),
+ format!("expected {expected} bound, found {got}"),
);
err.span_note(
tcx.def_span(assoc_item_def_id),
- &format!("{expected} defined here"),
+ format!("{expected} defined here"),
);
if let hir::def::DefKind::AssocConst = def_kind
@@ -1342,7 +1386,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
term = match def_kind {
hir::def::DefKind::AssocTy => tcx.ty_error(reported).into(),
hir::def::DefKind::AssocConst => tcx
- .const_error_with_guaranteed(
+ .const_error(
tcx.type_of(assoc_item_def_id)
.subst(tcx, projection_ty.skip_binder().substs),
reported,
@@ -1366,8 +1410,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
//
// Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
// parameter to have a skipped binder.
- let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder());
- self.add_bounds(param_ty, ast_bounds.iter(), bounds, projection_ty.bound_vars());
+ //
+ // NOTE: If `only_self_bounds` is true, do NOT expand this associated
+ // type bound into a trait predicate, since we only want to add predicates
+ // for the `Self` type.
+ if !only_self_bounds.0 {
+ let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder());
+ self.add_bounds(
+ param_ty,
+ ast_bounds.iter(),
+ bounds,
+ projection_ty.bound_vars(),
+ only_self_bounds,
+ );
+ }
}
}
Ok(())
@@ -1405,9 +1461,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&trait_bound.trait_ref,
trait_bound.span,
ty::BoundConstness::NotConst,
+ ty::ImplPolarity::Positive,
dummy_self,
&mut bounds,
false,
+ // FIXME: This should be `true`, but we don't really handle
+ // associated type bounds or type aliases in objects in a way
+ // that makes this meaningful, I think.
+ OnlySelfBounds(false),
) {
potential_assoc_types.extend(cur_potential_assoc_types);
}
@@ -1471,7 +1532,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
"additional use",
);
first_trait.label_with_exp_info(&mut err, "first non-auto trait", "first use");
- err.help(&format!(
+ err.help(format!(
"consider creating a new trait with all of these as supertraits and using that \
trait here instead: `trait NewTrait: {} {{}}`",
regular_traits
@@ -1781,7 +1842,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
([], []) => {
err.span_suggestion_verbose(
span,
- &format!(
+ format!(
"if there were a type named `Type` that implements a trait named \
`Trait` with associated type `{name}`, you could use the \
fully-qualified path",
@@ -1793,7 +1854,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
([], [trait_str]) => {
err.span_suggestion_verbose(
span,
- &format!(
+ format!(
"if there were a type named `Example` that implemented `{trait_str}`, \
you could use the fully-qualified path",
),
@@ -1804,7 +1865,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
([], traits) => {
err.span_suggestions(
span,
- &format!(
+ format!(
"if there were a type named `Example` that implemented one of the \
traits with associated type `{name}`, you could use the \
fully-qualified path",
@@ -1819,7 +1880,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
([type_str], []) => {
err.span_suggestion_verbose(
span,
- &format!(
+ format!(
"if there were a trait named `Example` with associated type `{name}` \
implemented for `{type_str}`, you could use the fully-qualified path",
),
@@ -1830,7 +1891,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
(types, []) => {
err.span_suggestions(
span,
- &format!(
+ format!(
"if there were a trait named `Example` with associated type `{name}` \
implemented for one of the types, you could use the fully-qualified \
path",
@@ -1885,7 +1946,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let param_name = tcx.hir().ty_param_name(ty_param_def_id);
self.one_bound_for_assoc_type(
|| {
- traits::transitive_bounds_that_define_assoc_type(
+ traits::transitive_bounds_that_define_assoc_item(
tcx,
predicates.iter().filter_map(|(p, _)| {
Some(p.to_opt_poly_trait_pred()?.map_bound(|t| t.trait_ref))
@@ -1996,7 +2057,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
);
}
} else {
- err.note(&format!(
+ err.note(format!(
"associated type `{}` could derive from `{}`",
ty_param_name,
bound.print_only_trait_path(),
@@ -2004,7 +2065,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
}
if !where_bounds.is_empty() {
- err.help(&format!(
+ err.help(format!(
"consider introducing a new type parameter `T` and adding `where` constraints:\
\n where\n T: {},\n{}",
ty_param_name,
@@ -2020,6 +2081,46 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
Ok(bound)
}
+ #[instrument(level = "debug", skip(self, all_candidates, ty_name), ret)]
+ fn one_bound_for_assoc_method(
+ &self,
+ all_candidates: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
+ ty_name: impl Display,
+ assoc_name: Ident,
+ span: Span,
+ ) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> {
+ let mut matching_candidates = all_candidates.filter(|r| {
+ self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Fn, assoc_name)
+ });
+
+ let candidate = match matching_candidates.next() {
+ Some(candidate) => candidate,
+ None => {
+ return Err(self.tcx().sess.emit_err(
+ crate::errors::ReturnTypeNotationMissingMethod {
+ span,
+ ty_name: ty_name.to_string(),
+ assoc_name: assoc_name.name,
+ },
+ ));
+ }
+ };
+
+ if let Some(conflicting_candidate) = matching_candidates.next() {
+ return Err(self.tcx().sess.emit_err(
+ crate::errors::ReturnTypeNotationConflictingBound {
+ span,
+ ty_name: ty_name.to_string(),
+ assoc_name: assoc_name.name,
+ first_bound: candidate.print_only_trait_path(),
+ second_bound: conflicting_candidate.print_only_trait_path(),
+ },
+ ));
+ }
+
+ Ok(candidate)
+ }
+
// Create a type from a path to an associated type or to an enum variant.
// For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C`
// and item_segment is the path segment for `D`. We return a type and a def for
@@ -2061,7 +2162,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
err.note("enum variants can't have type parameters");
let type_name = tcx.item_name(adt_def.did());
let msg = format!(
- "you might have meant to specity type parameters on enum \
+ "you might have meant to specify type parameters on enum \
`{type_name}`"
);
let Some(args) = assoc_segment.args else { return; };
@@ -2072,14 +2173,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// work for the `enum`, instead of just looking if it takes *any*.
err.span_suggestion_verbose(
args_span,
- &format!("{type_name} doesn't have generic parameters"),
+ format!("{type_name} doesn't have generic parameters"),
"",
Applicability::MachineApplicable,
);
return;
}
let Ok(snippet) = tcx.sess.source_map().span_to_snippet(args_span) else {
- err.note(&msg);
+ err.note(msg);
return;
};
let (qself_sugg_span, is_self) = if let hir::TyKind::Path(
@@ -2113,12 +2214,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
kw::SelfUpper == segment.ident.name,
),
_ => {
- err.note(&msg);
+ err.note(msg);
return;
}
}
} else {
- err.note(&msg);
+ err.note(msg);
return;
};
let suggestion = vec![
@@ -2133,7 +2234,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
(args_span, String::new()),
];
err.multipart_suggestion_verbose(
- &msg,
+ msg,
suggestion,
Applicability::MaybeIncorrect,
);
@@ -2185,7 +2286,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let reported = if variant_resolution.is_some() {
// Variant in type position
let msg = format!("expected type, found variant `{}`", assoc_ident);
- tcx.sess.span_err(span, &msg)
+ tcx.sess.span_err(span, msg)
} else if qself_ty.is_enum() {
let mut err = struct_span_err!(
tcx.sess,
@@ -2256,7 +2357,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// Assume that if it's not matched, there must be a const defined with the same name
// but it was used in a type position.
let msg = format!("found associated const `{assoc_ident}` when type was expected");
- let guar = tcx.sess.struct_span_err(span, &msg).emit();
+ let guar = tcx.sess.struct_span_err(span, msg).emit();
return Err(guar);
};
@@ -2276,7 +2377,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
also,
tcx.def_kind_descr(kind, def_id)
);
- lint.span_note(tcx.def_span(def_id), &note_msg);
+ lint.span_note(tcx.def_span(def_id), note_msg);
};
could_refer_to(DefKind::Variant, variant_def_id, "");
@@ -2317,19 +2418,25 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
return Ok(None);
}
+ //
+ // Select applicable inherent associated type candidates modulo regions.
+ //
+
// In contexts that have no inference context, just make a new one.
// We do need a local variable to store it, though.
let infcx_;
let infcx = match self.infcx() {
Some(infcx) => infcx,
None => {
- assert!(!self_ty.needs_infer());
+ assert!(!self_ty.has_infer());
infcx_ = tcx.infer_ctxt().ignoring_regions().build();
&infcx_
}
};
- let param_env = tcx.param_env(block.owner.to_def_id());
+ // FIXME(inherent_associated_types): Acquiring the ParamEnv this early leads to cycle errors
+ // when inside of an ADT (#108491) or where clause.
+ let param_env = tcx.param_env(block.owner);
let cause = ObligationCause::misc(span, block.owner.def_id);
let mut fulfillment_errors = Vec::new();
@@ -2337,6 +2444,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let universe = infcx.create_next_universe();
// Regions are not considered during selection.
+ // FIXME(non_lifetime_binders): Here we are "truncating" or "flattening" the universes
+ // of type and const binders. Is that correct in the selection phase? See also #109505.
let self_ty = tcx.replace_escaping_bound_vars_uncached(
self_ty,
FnMutDelegate {
@@ -2352,41 +2461,40 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
candidates
.iter()
- .filter_map(|&(impl_, (assoc_item, def_scope))| {
+ .copied()
+ .filter(|&(impl_, _)| {
infcx.probe(|_| {
let ocx = ObligationCtxt::new_in_snapshot(&infcx);
- let impl_ty = tcx.type_of(impl_);
let impl_substs = infcx.fresh_item_substs(impl_);
- let impl_ty = impl_ty.subst(tcx, impl_substs);
+ let impl_ty = tcx.type_of(impl_).subst(tcx, impl_substs);
let impl_ty = ocx.normalize(&cause, param_env, impl_ty);
- // Check that the Self-types can be related.
- // FIXME(fmease): Should we use `eq` here?
- ocx.sup(&ObligationCause::dummy(), param_env, impl_ty, self_ty).ok()?;
+ // Check that the self types can be related.
+ // FIXME(inherent_associated_types): Should we use `eq` here? Method probing uses
+ // `sup` for this situtation, too. What for? To constrain inference variables?
+ if ocx.sup(&ObligationCause::dummy(), param_env, impl_ty, self_ty).is_err()
+ {
+ return false;
+ }
// Check whether the impl imposes obligations we have to worry about.
- let impl_bounds = tcx.predicates_of(impl_);
- let impl_bounds = impl_bounds.instantiate(tcx, impl_substs);
-
+ let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_substs);
let impl_bounds = ocx.normalize(&cause, param_env, impl_bounds);
-
let impl_obligations = traits::predicates_for_generics(
|_, _| cause.clone(),
param_env,
impl_bounds,
);
-
ocx.register_obligations(impl_obligations);
let mut errors = ocx.select_where_possible();
if !errors.is_empty() {
fulfillment_errors.append(&mut errors);
- return None;
+ return false;
}
- // FIXME(fmease): Unsolved vars can escape this InferCtxt snapshot.
- Some((assoc_item, def_scope, infcx.resolve_vars_if_possible(impl_substs)))
+ true
})
})
.collect()
@@ -2395,24 +2503,26 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if applicable_candidates.len() > 1 {
return Err(self.complain_about_ambiguous_inherent_assoc_type(
name,
- applicable_candidates.into_iter().map(|(candidate, ..)| candidate).collect(),
+ applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(),
span,
));
}
- if let Some((assoc_item, def_scope, impl_substs)) = applicable_candidates.pop() {
+ if let Some((impl_, (assoc_item, def_scope))) = applicable_candidates.pop() {
self.check_assoc_ty(assoc_item, name, def_scope, block, span);
- // FIXME(inherent_associated_types): To fully *confirm* the *probed* candidate, we still
- // need to relate the Self-type with fresh item substs & register region obligations for
- // regionck to prove/disprove.
-
- let item_substs =
- self.create_substs_for_associated_item(span, assoc_item, segment, impl_substs);
+ // FIXME(fmease): Currently creating throwaway `parent_substs` to please
+ // `create_substs_for_associated_item`. Modify the latter instead (or sth. similar) to
+ // not require the parent substs logic.
+ let parent_substs = InternalSubsts::identity_for_item(tcx, impl_);
+ let substs =
+ self.create_substs_for_associated_item(span, assoc_item, segment, parent_substs);
+ let substs = tcx.mk_substs_from_iter(
+ std::iter::once(ty::GenericArg::from(self_ty))
+ .chain(substs.into_iter().skip(parent_substs.len())),
+ );
- // FIXME(fmease, #106722): Check if the bounds on the parameters of the
- // associated type hold, if any.
- let ty = tcx.type_of(assoc_item).subst(tcx, item_substs);
+ let ty = tcx.mk_alias(ty::Inherent, tcx.mk_alias_ty(assoc_item, substs));
return Ok(Some((ty, assoc_item)));
}
@@ -2473,9 +2583,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let msg = format!("{kind} `{name}` is private");
let def_span = tcx.def_span(item);
tcx.sess
- .struct_span_err_with_code(span, &msg, rustc_errors::error_code!(E0624))
- .span_label(span, &format!("private {kind}"))
- .span_label(def_span, &format!("{kind} defined here"))
+ .struct_span_err_with_code(span, msg, rustc_errors::error_code!(E0624))
+ .span_label(span, format!("private {kind}"))
+ .span_label(def_span, format!("{kind} defined here"))
.emit();
}
tcx.check_stability(item, Some(block), span, None);
@@ -2494,7 +2604,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let infcx = if let Some(infcx) = self.infcx() {
infcx
} else {
- assert!(!qself_ty.needs_infer());
+ assert!(!qself_ty.has_infer());
infcx_ = tcx.infer_ctxt().build();
&infcx_
};
@@ -2515,7 +2625,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&& tcx.all_impls(*trait_def_id)
.any(|impl_def_id| {
let trait_ref = tcx.impl_trait_ref(impl_def_id);
- trait_ref.map_or(false, |trait_ref| {
+ trait_ref.is_some_and(|trait_ref| {
let impl_ = trait_ref.subst(
tcx,
infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id),
@@ -2923,7 +3033,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self.prohibit_generics(path.segments.iter(), |err| {
if let Some(span) = tcx.def_ident_span(def_id) {
let name = tcx.item_name(def_id);
- err.span_note(span, &format!("type parameter `{name}` defined here"));
+ err.span_note(span, format!("type parameter `{name}` defined here"));
}
});
@@ -2984,7 +3094,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let mut span: MultiSpan = vec![t_sp].into();
span.push_span_label(
i_sp,
- &format!("`Self` is on type `{type_name}` in this `impl`"),
+ format!("`Self` is on type `{type_name}` in this `impl`"),
);
let mut postfix = "";
if generics == 0 {
@@ -2992,11 +3102,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
span.push_span_label(
t_sp,
- &format!("`Self` corresponds to this type{postfix}"),
+ format!("`Self` corresponds to this type{postfix}"),
);
- err.span_note(span, &msg);
+ err.span_note(span, msg);
} else {
- err.note(&msg);
+ err.note(msg);
}
for segment in path.segments {
if let Some(args) = segment.args && segment.ident.name == kw::SelfUpper {
@@ -3044,7 +3154,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// the anon const, which is empty. This is why the
// `AlwaysApplicable` impl needs a `T: ?Sized` bound for
// this to compile if we were to normalize here.
- if forbid_generic && ty.needs_subst() {
+ if forbid_generic && ty.has_param() {
let mut err = tcx.sess.struct_span_err(
path.span,
"generic `Self` types are currently not permitted in anonymous constants",
@@ -3087,7 +3197,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if let Some(args) = segment.args {
err.span_suggestion_verbose(
segment.ident.span.shrink_to_hi().to(args.span_ext),
- &format!("primitive type `{name}` doesn't have generic parameters"),
+ format!("primitive type `{name}` doesn't have generic parameters"),
"",
Applicability::MaybeIncorrect,
);
@@ -3378,7 +3488,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if !infer_replacements.is_empty() {
diag.multipart_suggestion(
- &format!(
+ format!(
"try replacing `_` with the type{} in the corresponding trait method signature",
rustc_errors::pluralize!(infer_replacements.len()),
),
@@ -3544,7 +3654,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
..
}) = tcx.hir().get_by_def_id(parent_id) && self_ty.hir_id == impl_self_ty.hir_id
{
- if !of_trait_ref.trait_def_id().map_or(false, |def_id| def_id.is_local()) {
+ if !of_trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) {
return;
}
let of_trait_span = of_trait_ref.path.span;
@@ -3583,7 +3693,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.source_map()
.span_to_prev_source(self_ty.span)
.ok()
- .map_or(false, |s| s.trim_end().ends_with('<'));
+ .is_some_and(|s| s.trim_end().ends_with('<'));
let is_global = poly_trait_ref.trait_ref.path.is_global();
@@ -3607,7 +3717,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
));
}
- if self_ty.span.edition() >= Edition::Edition2021 {
+ if self_ty.span.edition().rust_2021() {
let msg = "trait objects must include the `dyn` keyword";
let label = "add `dyn` keyword before this trait";
let mut diag =
@@ -3621,7 +3731,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
// check if the impl trait that we are considering is a impl of a local trait
self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag);
- diag.emit();
+ diag.stash(self_ty.span, StashKey::TraitMissingMethod);
} else {
let msg = "trait objects without an explicit `dyn` are deprecated";
tcx.struct_span_lint_hir(