summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis/src/astconv/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_hir_analysis/src/astconv/mod.rs')
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs618
1 files changed, 250 insertions, 368 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 2fcb45ef8..6f8e80172 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -18,29 +18,30 @@ use crate::require_c_abi_if_c_variadic;
use rustc_ast::TraitObjectSyntax;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{
- struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, FatalError,
- MultiSpan,
+ error_code, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
+ FatalError, MultiSpan,
};
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{walk_generics, Visitor as _};
use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
-use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
+use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::ObligationCause;
use rustc_middle::middle::stability::AllowUnstable;
use rustc_middle::ty::GenericParamDefKind;
use rustc_middle::ty::{
- self, Const, GenericArgKind, GenericArgsRef, IsSuggestable, Ty, TyCtxt, TypeVisitableExt,
+ self, Const, GenericArgKind, GenericArgsRef, IsSuggestable, ParamEnv, Ty, TyCtxt,
+ TypeVisitableExt,
};
use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
use rustc_span::edit_distance::find_best_match_for_name;
+use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::{sym, BytePos, Span, DUMMY_SP};
use rustc_target::spec::abi;
use rustc_trait_selection::traits::wf::object_region_bounds;
-use rustc_trait_selection::traits::{self, NormalizeExt, ObligationCtxt};
-use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
+use rustc_trait_selection::traits::{self, ObligationCtxt};
use std::fmt::Display;
use std::slice;
@@ -162,7 +163,7 @@ struct ConvertedBinding<'a, 'tcx> {
#[derive(Debug)]
enum ConvertedBindingKind<'a, 'tcx> {
- Equality(ty::Term<'tcx>),
+ Equality(Spanned<ty::Term<'tcx>>),
Constraint(&'a [hir::GenericBound<'a>]),
}
@@ -239,7 +240,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
def: Option<&ty::GenericParamDef>,
) -> ty::Region<'tcx> {
let tcx = self.tcx();
- let lifetime_name = |def_id| tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id));
+ let lifetime_name = |def_id| tcx.hir().name(tcx.local_def_id_to_hir_id(def_id));
match tcx.named_bound_var(lifetime.hir_id) {
Some(rbv::ResolvedArg::StaticLifetime) => tcx.lifetimes.re_static,
@@ -250,7 +251,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
var: ty::BoundVar::from_u32(index),
kind: ty::BrNamed(def_id, name),
};
- ty::Region::new_late_bound(tcx, debruijn, br)
+ ty::Region::new_bound(tcx, debruijn, br)
}
Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
@@ -258,12 +259,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local());
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id];
- ty::Region::new_early_bound(tcx, ty::EarlyBoundRegion { def_id, index, name })
+ ty::Region::new_early_param(tcx, ty::EarlyParamRegion { def_id, index, name })
}
Some(rbv::ResolvedArg::Free(scope, id)) => {
let name = lifetime_name(id.expect_local());
- ty::Region::new_free(tcx, scope, ty::BrNamed(id, name))
+ ty::Region::new_late_param(tcx, scope, ty::BrNamed(id, name))
// (*) -- not late-bound, won't change
}
@@ -476,7 +477,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
ty::Const::new_misc_error(tcx, ty).into()
}
}
- _ => unreachable!(),
+ (kind, arg) => span_bug!(
+ self.span,
+ "mismatched path argument for kind {kind:?}: found arg {arg:?}"
+ ),
}
}
@@ -595,12 +599,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.map(|binding| {
let kind = match &binding.kind {
hir::TypeBindingKind::Equality { term } => match term {
- hir::Term::Ty(ty) => {
- ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty).into())
- }
+ hir::Term::Ty(ty) => ConvertedBindingKind::Equality(respan(
+ ty.span,
+ self.ast_ty_to_ty(ty).into(),
+ )),
hir::Term::Const(c) => {
+ let span = self.tcx().def_span(c.def_id);
let c = Const::from_anon_const(self.tcx(), c.def_id);
- ConvertedBindingKind::Equality(c.into())
+ ConvertedBindingKind::Equality(respan(span, c.into()))
}
},
hir::TypeBindingKind::Constraint { bounds } => {
@@ -672,36 +678,57 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
)
}
- fn instantiate_poly_trait_ref_inner(
+ /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct
+ /// a full trait reference. The resulting trait reference is returned. This may also generate
+ /// auxiliary bounds, which are added to `bounds`.
+ ///
+ /// Example:
+ ///
+ /// ```ignore (illustrative)
+ /// poly_trait_ref = Iterator<Item = u32>
+ /// self_ty = Foo
+ /// ```
+ ///
+ /// this would return `Foo: Iterator` and add `<Foo as Iterator>::Item = u32` into `bounds`.
+ ///
+ /// **A note on binders:** against our usual convention, there is an implied binder around
+ /// the `self_ty` and `poly_trait_ref` parameters here. So they may reference bound regions.
+ /// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>`
+ /// where `'a` is a bound region at depth 0. Similarly, the `poly_trait_ref` would be
+ /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly,
+ /// however.
+ #[instrument(level = "debug", skip(self, span, constness, bounds, speculative))]
+ pub(crate) fn instantiate_poly_trait_ref(
&self,
- hir_id: hir::HirId,
+ trait_ref: &hir::TraitRef<'_>,
span: Span,
- binding_span: Option<Span>,
constness: ty::BoundConstness,
polarity: ty::ImplPolarity,
+ self_ty: Ty<'tcx>,
bounds: &mut Bounds<'tcx>,
speculative: bool,
- trait_ref_span: Span,
- trait_def_id: DefId,
- trait_segment: &hir::PathSegment<'_>,
- args: &GenericArgs<'_>,
- infer_args: bool,
- self_ty: Ty<'tcx>,
only_self_bounds: OnlySelfBounds,
) -> GenericArgCountResult {
+ let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
+ let trait_segment = trait_ref.path.segments.last().unwrap();
+ let args = trait_segment.args();
+
+ self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {});
+ self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, false);
+
let (generic_args, arg_count) = self.create_args_for_ast_path(
- trait_ref_span,
+ trait_ref.path.span,
trait_def_id,
&[],
trait_segment,
args,
- infer_args,
+ trait_segment.infer_args,
Some(self_ty),
constness,
);
let tcx = self.tcx();
- let bound_vars = tcx.late_bound_vars(hir_id);
+ let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id);
debug!(?bound_vars);
let assoc_bindings = self.create_assoc_bindings_for_generic_args(args);
@@ -720,21 +747,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// 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");
+ self.tcx().sess.span_delayed_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,
+ trait_ref.hir_ref_id,
poly_trait_ref,
binding,
bounds,
speculative,
&mut dup_bindings,
- binding_span.unwrap_or(binding.span),
+ binding.span,
constness,
only_self_bounds,
polarity,
@@ -745,102 +773,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
arg_count
}
- /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct
- /// a full trait reference. The resulting trait reference is returned. This may also generate
- /// auxiliary bounds, which are added to `bounds`.
- ///
- /// Example:
- ///
- /// ```ignore (illustrative)
- /// poly_trait_ref = Iterator<Item = u32>
- /// self_ty = Foo
- /// ```
- ///
- /// this would return `Foo: Iterator` and add `<Foo as Iterator>::Item = u32` into `bounds`.
- ///
- /// **A note on binders:** against our usual convention, there is an implied bounder around
- /// the `self_ty` and `poly_trait_ref` parameters here. So they may reference bound regions.
- /// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>`
- /// where `'a` is a bound region at depth 0. Similarly, the `poly_trait_ref` would be
- /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly,
- /// however.
- #[instrument(level = "debug", skip(self, span, constness, bounds, speculative))]
- pub(crate) fn instantiate_poly_trait_ref(
- &self,
- 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;
- let trait_ref_span = trait_ref.path.span;
- let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
- let trait_segment = trait_ref.path.segments.last().unwrap();
- let args = trait_segment.args();
- let infer_args = trait_segment.infer_args;
-
- self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {});
- self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, false);
-
- self.instantiate_poly_trait_ref_inner(
- hir_id,
- span,
- binding_span,
- constness,
- polarity,
- bounds,
- speculative,
- trait_ref_span,
- trait_def_id,
- trait_segment,
- args,
- infer_args,
- self_ty,
- only_self_bounds,
- )
- }
-
- pub(crate) fn instantiate_lang_item_trait_ref(
- &self,
- lang_item: hir::LangItem,
- span: Span,
- hir_id: hir::HirId,
- args: &GenericArgs<'_>,
- self_ty: Ty<'tcx>,
- bounds: &mut Bounds<'tcx>,
- only_self_bounds: OnlySelfBounds,
- ) {
- let binding_span = Some(span);
- let constness = ty::BoundConstness::NotConst;
- let speculative = false;
- let trait_ref_span = span;
- let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span));
- let trait_segment = &hir::PathSegment::invalid();
- let infer_args = false;
-
- self.instantiate_poly_trait_ref_inner(
- hir_id,
- span,
- binding_span,
- constness,
- ty::ImplPolarity::Positive,
- bounds,
- speculative,
- trait_ref_span,
- trait_def_id,
- trait_segment,
- args,
- infer_args,
- self_ty,
- only_self_bounds,
- );
- }
-
fn ast_path_to_mono_trait_ref(
&self,
span: Span,
@@ -945,7 +877,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
Applicability::MachineApplicable,
);
} else {
- match (types, traits) {
+ let mut types = types.to_vec();
+ types.sort();
+ let mut traits = traits.to_vec();
+ traits.sort();
+ match (&types[..], &traits[..]) {
([], []) => {
err.span_suggestion_verbose(
span,
@@ -1051,7 +987,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
debug!("find_bound_for_assoc_item: predicates={:#?}", predicates);
let param_name = tcx.hir().ty_param_name(ty_param_def_id);
- self.one_bound_for_assoc_type(
+ self.one_bound_for_assoc_item(
|| {
traits::transitive_bounds_that_define_assoc_item(
tcx,
@@ -1063,6 +999,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
},
param_name,
Some(ty_param_def_id),
+ ty::AssocKind::Type,
assoc_name,
span,
None,
@@ -1071,48 +1008,45 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// Checks that `bounds` contains exactly one element and reports appropriate
// errors otherwise.
- #[instrument(level = "debug", skip(self, all_candidates, ty_param_name, is_equality), ret)]
- fn one_bound_for_assoc_type<I>(
+ #[instrument(level = "debug", skip(self, all_candidates, ty_param_name, binding), ret)]
+ fn one_bound_for_assoc_item<I>(
&self,
all_candidates: impl Fn() -> I,
ty_param_name: impl Display,
ty_param_def_id: Option<LocalDefId>,
+ assoc_kind: ty::AssocKind,
assoc_name: Ident,
span: Span,
- is_equality: Option<ty::Term<'tcx>>,
+ binding: Option<&ConvertedBinding<'_, 'tcx>>,
) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed>
where
I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
{
+ let tcx = self.tcx();
+
let mut matching_candidates = all_candidates().filter(|r| {
- self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Type, assoc_name)
- });
- let mut const_candidates = all_candidates().filter(|r| {
- self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Const, assoc_name)
+ self.trait_defines_associated_item_named(r.def_id(), assoc_kind, assoc_name)
});
- let (mut bound, mut next_cand) = match (matching_candidates.next(), const_candidates.next())
- {
- (Some(bound), _) => (bound, matching_candidates.next()),
- (None, Some(bound)) => (bound, const_candidates.next()),
- (None, None) => {
- let reported = self.complain_about_assoc_type_not_found(
- all_candidates,
- &ty_param_name.to_string(),
- ty_param_def_id,
- assoc_name,
- span,
- );
- return Err(reported);
- }
+ let Some(mut bound) = matching_candidates.next() else {
+ let reported = self.complain_about_assoc_item_not_found(
+ all_candidates,
+ &ty_param_name.to_string(),
+ ty_param_def_id,
+ assoc_kind,
+ assoc_name,
+ span,
+ binding,
+ );
+ return Err(reported);
};
debug!(?bound);
// look for a candidate that is not the same as our first bound, disregarding
// whether the bound is const.
+ let mut next_cand = matching_candidates.next();
while let Some(mut bound2) = next_cand {
debug!(?bound2);
- let tcx = self.tcx();
if bound2.bound_vars() != bound.bound_vars() {
break;
}
@@ -1133,7 +1067,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.map(|(n, arg)| if host_index == n { tcx.consts.true_.into() } else { arg });
if unconsted_args.eq(bound2.skip_binder().args.iter()) {
- next_cand = matching_candidates.next().or_else(|| const_candidates.next());
+ next_cand = matching_candidates.next();
} else {
break;
}
@@ -1142,51 +1076,53 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if let Some(bound2) = next_cand {
debug!(?bound2);
- let bounds = IntoIterator::into_iter([bound, bound2]).chain(matching_candidates);
- let mut err = if is_equality.is_some() {
- // More specific Error Index entry.
- struct_span_err!(
- self.tcx().sess,
- span,
- E0222,
- "ambiguous associated type `{}` in bounds of `{}`",
- assoc_name,
- ty_param_name
- )
- } else {
- struct_span_err!(
- self.tcx().sess,
- span,
- E0221,
- "ambiguous associated type `{}` in bounds of `{}`",
- assoc_name,
- ty_param_name
- )
- };
- err.span_label(span, format!("ambiguous associated type `{assoc_name}`"));
+ let assoc_kind_str = assoc_kind_str(assoc_kind);
+ let ty_param_name = &ty_param_name.to_string();
+ let mut err = tcx.sess.create_err(crate::errors::AmbiguousAssocItem {
+ span,
+ assoc_kind: assoc_kind_str,
+ assoc_name,
+ ty_param_name,
+ });
+ // Provide a more specific error code index entry for equality bindings.
+ err.code(
+ if let Some(binding) = binding
+ && let ConvertedBindingKind::Equality(_) = binding.kind
+ {
+ error_code!(E0222)
+ } else {
+ error_code!(E0221)
+ },
+ );
+ // FIXME(#97583): Resugar equality bounds to type/const bindings.
+ // FIXME: Turn this into a structured, translateable & more actionable suggestion.
let mut where_bounds = vec![];
- for bound in bounds {
+ for bound in [bound, bound2].into_iter().chain(matching_candidates) {
let bound_id = bound.def_id();
- let bound_span = self
- .tcx()
+ let bound_span = tcx
.associated_items(bound_id)
- .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, bound_id)
- .and_then(|item| self.tcx().hir().span_if_local(item.def_id));
+ .find_by_name_and_kind(tcx, assoc_name, assoc_kind, bound_id)
+ .and_then(|item| tcx.hir().span_if_local(item.def_id));
if let Some(bound_span) = bound_span {
err.span_label(
bound_span,
- format!(
- "ambiguous `{assoc_name}` from `{}`",
- bound.print_only_trait_path(),
- ),
+ format!("ambiguous `{assoc_name}` from `{}`", bound.print_trait_sugared(),),
);
- if let Some(constraint) = &is_equality {
- where_bounds.push(format!(
- " T: {trait}::{assoc_name} = {constraint}",
- trait=bound.print_only_trait_path(),
- ));
+ if let Some(binding) = binding {
+ match binding.kind {
+ ConvertedBindingKind::Equality(term) => {
+ // FIXME(#97583): This isn't syntactically well-formed!
+ where_bounds.push(format!(
+ " T: {trait}::{assoc_name} = {term}",
+ trait = bound.print_only_trait_path(),
+ term = term.node,
+ ));
+ }
+ // FIXME: Provide a suggestion.
+ ConvertedBindingKind::Constraint(_bounds) => {}
+ }
} else {
err.span_suggestion_verbose(
span.with_hi(assoc_name.span.lo()),
@@ -1197,7 +1133,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
} else {
err.note(format!(
- "associated type `{ty_param_name}` could derive from `{}`",
+ "associated {assoc_kind_str} `{assoc_name}` could derive from `{}`",
bound.print_only_trait_path(),
));
}
@@ -1218,46 +1154,6 @@ 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
@@ -1415,11 +1311,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// trait reference.
let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else {
// A cycle error occurred, most likely.
- let guar = tcx.sess.delay_span_bug(span, "expected cycle error");
+ let guar = tcx.sess.span_delayed_bug(span, "expected cycle error");
return Err(guar);
};
- self.one_bound_for_assoc_type(
+ self.one_bound_for_assoc_item(
|| {
traits::supertraits(
tcx,
@@ -1428,6 +1324,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
},
kw::SelfUpper,
None,
+ ty::AssocKind::Type,
assoc_ident,
span,
None,
@@ -1508,15 +1405,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
};
let trait_did = bound.def_id();
- let Some(assoc_ty_did) = self.lookup_assoc_ty(assoc_ident, hir_ref_id, span, trait_did)
- else {
- // 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();
- return Err(guar);
- };
-
+ let assoc_ty_did = self.lookup_assoc_ty(assoc_ident, hir_ref_id, span, trait_did).unwrap();
let ty = self.projected_ty_from_poly_trait_ref(span, assoc_ty_did, assoc_segment, bound);
if let Some(variant_def_id) = variant_resolution {
@@ -1545,8 +1434,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident),
Applicability::MachineApplicable,
);
-
- lint
},
);
}
@@ -1602,134 +1489,110 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// 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();
- let mut applicable_candidates: Vec<_> = infcx.probe(|_| {
- // Regions are not considered during selection.
- let self_ty = self_ty
- .fold_with(&mut BoundVarEraser { tcx, universe: infcx.create_next_universe() });
-
- struct BoundVarEraser<'tcx> {
- tcx: TyCtxt<'tcx>,
- universe: ty::UniverseIndex,
- }
- // FIXME(non_lifetime_binders): Don't assign the same universe to each placeholder.
- impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarEraser<'tcx> {
- fn interner(&self) -> TyCtxt<'tcx> {
- self.tcx
- }
+ let mut universes = if self_ty.has_escaping_bound_vars() {
+ vec![None; self_ty.outer_exclusive_binder().as_usize()]
+ } else {
+ vec![]
+ };
- fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
- if r.is_late_bound() { self.tcx.lifetimes.re_erased } else { r }
- }
+ let (impl_, (assoc_item, def_scope)) =
+ crate::traits::project::with_replaced_escaping_bound_vars(
+ infcx,
+ &mut universes,
+ self_ty,
+ |self_ty| {
+ self.select_inherent_assoc_type_candidates(
+ infcx, name, span, self_ty, param_env, candidates,
+ )
+ },
+ )?;
+
+ self.check_assoc_ty(assoc_item, name, def_scope, block, span);
+
+ // FIXME(fmease): Currently creating throwaway `parent_args` to please
+ // `create_args_for_associated_item`. Modify the latter instead (or sth. similar) to
+ // not require the parent args logic.
+ let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_);
+ let args = self.create_args_for_associated_item(span, assoc_item, segment, parent_args);
+ let args = tcx.mk_args_from_iter(
+ std::iter::once(ty::GenericArg::from(self_ty))
+ .chain(args.into_iter().skip(parent_args.len())),
+ );
- fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
- match *ty.kind() {
- ty::Bound(_, bv) => Ty::new_placeholder(
- self.tcx,
- ty::PlaceholderType { universe: self.universe, bound: bv },
- ),
- _ => ty.super_fold_with(self),
- }
- }
+ let ty = Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new(tcx, assoc_item, args));
- fn fold_const(
- &mut self,
- ct: ty::Const<'tcx>,
- ) -> <TyCtxt<'tcx> as rustc_type_ir::Interner>::Const {
- assert!(!ct.ty().has_escaping_bound_vars());
-
- match ct.kind() {
- ty::ConstKind::Bound(_, bv) => ty::Const::new_placeholder(
- self.tcx,
- ty::PlaceholderConst { universe: self.universe, bound: bv },
- ct.ty(),
- ),
- _ => ct.super_fold_with(self),
- }
- }
- }
+ Ok(Some((ty, assoc_item)))
+ }
- let InferOk { value: self_ty, obligations } =
- infcx.at(&cause, param_env).normalize(self_ty);
+ fn select_inherent_assoc_type_candidates(
+ &self,
+ infcx: &InferCtxt<'tcx>,
+ name: Ident,
+ span: Span,
+ self_ty: Ty<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ candidates: Vec<(DefId, (DefId, DefId))>,
+ ) -> Result<(DefId, (DefId, DefId)), ErrorGuaranteed> {
+ let tcx = self.tcx();
+ let mut fulfillment_errors = Vec::new();
- candidates
- .iter()
- .copied()
- .filter(|&(impl_, _)| {
- infcx.probe(|_| {
- let ocx = ObligationCtxt::new(&infcx);
- ocx.register_obligations(obligations.clone());
-
- let impl_args = infcx.fresh_args_for_item(span, impl_);
- let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args);
- let impl_ty = ocx.normalize(&cause, param_env, impl_ty);
-
- // 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;
- }
+ let applicable_candidates: Vec<_> = candidates
+ .iter()
+ .copied()
+ .filter(|&(impl_, _)| {
+ infcx.probe(|_| {
+ let ocx = ObligationCtxt::new(infcx);
+ let self_ty = ocx.normalize(&ObligationCause::dummy(), param_env, self_ty);
+
+ let impl_args = infcx.fresh_args_for_item(span, impl_);
+ let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args);
+ let impl_ty = ocx.normalize(&ObligationCause::dummy(), param_env, impl_ty);
+
+ // Check that the self types can be related.
+ if ocx.eq(&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_).instantiate(tcx, impl_args);
- 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);
+ // Check whether the impl imposes obligations we have to worry about.
+ let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args);
+ let impl_bounds =
+ ocx.normalize(&ObligationCause::dummy(), param_env, impl_bounds);
+ let impl_obligations = traits::predicates_for_generics(
+ |_, _| ObligationCause::dummy(),
+ 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 false;
- }
+ let mut errors = ocx.select_where_possible();
+ if !errors.is_empty() {
+ fulfillment_errors.append(&mut errors);
+ return false;
+ }
- true
- })
+ true
})
- .collect()
- });
+ })
+ .collect();
- if applicable_candidates.len() > 1 {
- return Err(self.complain_about_ambiguous_inherent_assoc_type(
+ match &applicable_candidates[..] {
+ &[] => Err(self.complain_about_inherent_assoc_type_not_found(
name,
- applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(),
+ self_ty,
+ candidates,
+ fulfillment_errors,
span,
- ));
- }
+ )),
- if let Some((impl_, (assoc_item, def_scope))) = applicable_candidates.pop() {
- self.check_assoc_ty(assoc_item, name, def_scope, block, span);
-
- // FIXME(fmease): Currently creating throwaway `parent_args` to please
- // `create_args_for_associated_item`. Modify the latter instead (or sth. similar) to
- // not require the parent args logic.
- let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_);
- let args = self.create_args_for_associated_item(span, assoc_item, segment, parent_args);
- let args = tcx.mk_args_from_iter(
- std::iter::once(ty::GenericArg::from(self_ty))
- .chain(args.into_iter().skip(parent_args.len())),
- );
+ &[applicable_candidate] => Ok(applicable_candidate),
- let ty = Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new(tcx, assoc_item, args));
-
- return Ok(Some((ty, assoc_item)));
+ &[_, ..] => Err(self.complain_about_ambiguous_inherent_assoc_type(
+ name,
+ applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(),
+ span,
+ )),
}
-
- Err(self.complain_about_inherent_assoc_type_not_found(
- name,
- self_ty,
- candidates,
- fulfillment_errors,
- span,
- ))
}
fn lookup_assoc_ty(
@@ -1753,8 +1616,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let tcx = self.tcx();
let (ident, def_scope) = tcx.adjust_ident_and_get_scope(name, scope, block);
- // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead
- // of calling `find_by_name_and_kind`.
+ // We have already adjusted the item name above, so compare with `.normalize_to_macros_2_0()`
+ // instead of calling `filter_by_name_and_kind` which would needlessly normalize the
+ // `ident` again and again.
let item = tcx.associated_items(scope).in_definition_order().find(|i| {
i.kind.namespace() == Namespace::TypeNS
&& i.ident(tcx).normalize_to_macros_2_0() == ident
@@ -1869,7 +1733,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let parent_def_id = def_id
.as_local()
- .map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
+ .map(|def_id| tcx.local_def_id_to_hir_id(def_id))
.map(|hir_id| tcx.hir().get_parent_item(hir_id).to_def_id());
debug!("qpath_to_ty: parent_def_id={:?}", parent_def_id);
@@ -1973,7 +1837,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
types_and_spans[..types_and_spans.len() - 1]
.iter()
.map(|(x, _)| x.as_str())
- .intersperse(&", ")
+ .intersperse(", ")
.collect::<String>()
),
[(only, _)] => only.to_string(),
@@ -2008,7 +1872,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
"s",
),
[only] => (only.to_string(), ""),
- [] => unreachable!(),
+ [] => unreachable!("expected at least one generic to prohibit"),
};
let last_span = *arg_spans.last().unwrap();
let span: MultiSpan = arg_spans.into();
@@ -2396,7 +2260,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let e = self
.tcx()
.sess
- .delay_span_bug(path.span, "path with `Res::Err` but no error emitted");
+ .span_delayed_bug(path.span, "path with `Res::Err` but no error emitted");
self.set_tainted_by_errors(e);
Ty::new_error(self.tcx(), e)
}
@@ -2543,7 +2407,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.map(|(ty, _, _)| ty)
.unwrap_or_else(|guar| Ty::new_error(tcx, guar))
}
- &hir::TyKind::Path(hir::QPath::LangItem(lang_item, span, _)) => {
+ &hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => {
let def_id = tcx.require_lang_item(lang_item, Some(span));
let (args, _) = self.create_args_for_ast_path(
span,
@@ -2617,8 +2481,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if let Some(i) = (param.index as usize).checked_sub(generics.count() - lifetimes.len())
{
// Resolve our own lifetime parameters.
- let GenericParamDefKind::Lifetime { .. } = param.kind else { bug!() };
- let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] else { bug!() };
+ let GenericParamDefKind::Lifetime { .. } = param.kind else {
+ span_bug!(
+ tcx.def_span(param.def_id),
+ "only expected lifetime for opaque's own generics, got {:?}",
+ param.kind
+ );
+ };
+ let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] else {
+ bug!(
+ "expected lifetime argument for param {param:?}, found {:?}",
+ &lifetimes[i]
+ )
+ };
self.ast_region_to_region(lifetime, None).into()
} else {
tcx.mk_param_from_def(param)
@@ -2777,7 +2652,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let hir = tcx.hir();
let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), ident, .. }) =
- hir.get(fn_hir_id)
+ tcx.hir_node(fn_hir_id)
else {
return None;
};
@@ -2845,6 +2720,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
/// provided, if they provided one, and otherwise search the supertypes of trait bounds
/// for region bounds. It may be that we can derive no bound at all, in which case
/// we return `None`.
+ #[instrument(level = "debug", skip(self, span), ret)]
fn compute_object_lifetime_bound(
&self,
span: Span,
@@ -2853,8 +2729,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
{
let tcx = self.tcx();
- debug!("compute_opt_region_bound(existential_predicates={:?})", existential_predicates);
-
// No explicit region bound specified. Therefore, examine trait
// bounds and see if we can derive region bounds from those.
let derived_region_bounds = object_region_bounds(tcx, existential_predicates);
@@ -2881,3 +2755,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
Some(r)
}
}
+
+fn assoc_kind_str(kind: ty::AssocKind) -> &'static str {
+ match kind {
+ ty::AssocKind::Fn => "function",
+ ty::AssocKind::Const => "constant",
+ ty::AssocKind::Type => "type",
+ }
+}