diff options
Diffstat (limited to 'compiler/rustc_hir_analysis/src/astconv/mod.rs')
-rw-r--r-- | compiler/rustc_hir_analysis/src/astconv/mod.rs | 328 |
1 files changed, 219 insertions, 109 deletions
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), ¬e_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( |