diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index d14aef8ace46e..f37fb7c913ef0 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -559,6 +559,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { constraint.ident, path_span, Some(constraint), + ) + .select_bound( + self, + AssocItemQSelf::Trait(trait_ref.def_id()), + assoc_tag, + constraint.ident, + path_span, + Some(constraint), )? }; @@ -806,18 +814,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }) => { let self_ty = self.lower_ty(hir_self_ty); - let (item_def_id, bound) = match self.resolve_type_relative_path( - self_ty, - hir_self_ty, - ty::AssocTag::Fn, - segment, - hir_ty.hir_id, - hir_ty.span, - None, - ) { - Ok(result) => result, - Err(guar) => return Ty::new_error(tcx, guar), - }; + + // FIXME(unresolved_aliases): Force a resolution here + todo!() + + // let (item_def_id, bound) = match self.resolve_type_relative_path( + // self_ty, + // hir_self_ty, + // ty::AssocTag::Fn, + // segment, + // hir_ty.hir_id, + // hir_ty.span, + // None, + // ) { + // Ok(result) => result, + // Err(guar) => return Ty::new_error(tcx, guar), + // }; // Don't let `T::method` resolve to some `for<'a> >::method`, // which may happen via a higher-ranked where clause or supertrait. @@ -825,23 +837,23 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // support it, it just makes things a lot more difficult to support in // `resolve_bound_vars`, since we'd need to introduce those as elided // bound vars on the where clause too. - if bound.has_bound_vars() { - return Ty::new_error( - tcx, - self.dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams { - span: hir_ty.span, - inferred_sugg: Some(hir_ty.span.with_hi(segment.ident.span.lo())), - bound: format!("{}::", tcx.anonymize_bound_vars(bound).skip_binder()), - mpart_sugg: None, - what: tcx.def_descr(item_def_id), - }), - ); - } - - match self.lower_return_type_notation_ty(bound, item_def_id, hir_ty.span) { - Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty), - Err(guar) => Ty::new_error(tcx, guar), - } + // if bound.has_bound_vars() { + // return Ty::new_error( + // tcx, + // self.dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams { + // span: hir_ty.span, + // inferred_sugg: Some(hir_ty.span.with_hi(segment.ident.span.lo())), + // bound: format!("{}::", tcx.anonymize_bound_vars(bound).skip_binder()), + // mpart_sugg: None, + // what: tcx.def_descr(item_def_id), + // }), + // ); + // } + + // match self.lower_return_type_notation_ty(bound, item_def_id, hir_ty.span) { + // Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty), + // Err(guar) => Ty::new_error(tcx, guar), + // } } _ => self.lower_ty(hir_ty), } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index c7b984d9b259c..eedf67db268cc 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -56,7 +56,16 @@ use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation}; use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint}; use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args}; use crate::middle::resolve_bound_vars as rbv; -use crate::require_c_abi_if_c_variadic; +use crate::{Providers, require_c_abi_if_c_variadic}; + +pub fn provide(providers: &mut Providers) { + *providers = Providers { + candidates_for_unresolved_alias: |_, def| { + bug!("Unexpected non unresolved-alias def `{def:?}`") + }, + ..*providers + }; +} /// A path segment that is semantically allowed to have generic arguments. #[derive(Debug)] @@ -373,6 +382,134 @@ pub trait GenericArgsLowerer<'a, 'tcx> { ) -> ty::GenericArg<'tcx>; } +#[derive(Debug, Clone)] +pub struct TypeRelativePathCandidates { + pub candidates: Vec<(DefId, ty::PolyTraitRef<'tcx>)>, +} + +#[derive(Debug, Clone)] +pub struct ProbeBoundCandidates<'tcx> { + pub all_candidates: Vec>, + pub matching_candidates: Vec>, +} + +impl<'tcx> ProbeBoundCandidates<'tcx> { + pub fn select_bound( + self, + ty_lowerer: &dyn HirTyLowerer<'tcx>, + qself: AssocItemQSelf, + assoc_tag: ty::AssocTag, + assoc_ident: Ident, + span: Span, + constraint: Option<&hir::AssocItemConstraint<'tcx>>, + ) -> Result, ErrorGuaranteed> { + let tcx = ty_lowerer.tcx(); + + let all_candidates = || self.all_candidates.iter().copied(); + let mut matching_candidates = self.matching_candidates.iter().copied(); + + let Some(bound) = matching_candidates.next() else { + return Err(ty_lowerer.report_unresolved_assoc_item( + all_candidates, + qself, + assoc_tag, + assoc_ident, + span, + constraint, + )); + }; + debug!(?bound); + + if let Some(bound2) = matching_candidates.next() { + debug!(?bound2); + + let assoc_kind_str = errors::assoc_tag_str(assoc_tag); + let qself_str = qself.to_string(tcx); + let mut err = ty_lowerer.dcx().create_err(crate::errors::AmbiguousAssocItem { + span, + assoc_kind: assoc_kind_str, + assoc_ident, + qself: &qself_str, + }); + // Provide a more specific error code index entry for equality bindings. + err.code( + if let Some(constraint) = constraint + && let hir::AssocItemConstraintKind::Equality { .. } = constraint.kind + { + E0222 + } else { + E0221 + }, + ); + + // FIXME(#97583): Print associated item bindings properly (i.e., not as equality + // predicates!). + // FIXME: Turn this into a structured, translatable & more actionable suggestion. + let mut where_bounds = vec![]; + for bound in [bound, bound2].into_iter().chain(matching_candidates) { + let bound_id = bound.def_id(); + let bound_span = tcx + .associated_items(bound_id) + .find_by_ident_and_kind(tcx, assoc_ident, assoc_tag, 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_ident}` from `{}`", bound.print_trait_sugared(),), + ); + if let Some(constraint) = constraint { + match constraint.kind { + hir::AssocItemConstraintKind::Equality { term } => { + let term: ty::Term<'_> = match term { + hir::Term::Ty(ty) => ty_lowerer.lower_ty(ty).into(), + hir::Term::Const(ct) => { + ty_lowerer.lower_const_arg(ct, FeedConstTy::No).into() + } + }; + if term.references_error() { + continue; + } + // FIXME(#97583): This isn't syntactically well-formed! + where_bounds.push(format!( + " T: {trait}::{assoc_ident} = {term}", + trait = bound.print_only_trait_path(), + )); + } + // FIXME: Provide a suggestion. + hir::AssocItemConstraintKind::Bound { bounds: _ } => {} + } + } else { + err.span_suggestion_verbose( + span.with_hi(assoc_ident.span.lo()), + "use fully-qualified syntax to disambiguate", + format!("<{qself_str} as {}>::", bound.print_only_trait_path()), + Applicability::MaybeIncorrect, + ); + } + } else { + err.note(format!( + "associated {assoc_kind_str} `{assoc_ident}` could derive from `{}`", + bound.print_only_trait_path(), + )); + } + } + if !where_bounds.is_empty() { + err.help(format!( + "consider introducing a new type parameter `T` and adding `where` constraints:\ + \n where\n T: {qself_str},\n{}", + where_bounds.join(",\n"), + )); + let reported = err.emit(); + return Err(reported); + } + err.emit(); + } + + Ok(bound) + } +} + impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// Lower a lifetime from the HIR to our internal notion of a lifetime called a *region*. #[instrument(level = "debug", skip(self), ret)] @@ -1009,7 +1146,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { assoc_tag: ty::AssocTag, assoc_ident: Ident, span: Span, - ) -> Result, ErrorGuaranteed> { + ) -> ProbeBoundCandidates<'tcx> { debug!(?ty_param_def_id, ?assoc_ident, ?span); let tcx = self.tcx(); @@ -1045,7 +1182,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { assoc_ident: Ident, span: Span, constraint: Option<&hir::AssocItemConstraint<'tcx>>, - ) -> Result, ErrorGuaranteed> + ) -> ProbeBoundCandidates<'tcx> where I: Iterator>, { @@ -1055,106 +1192,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.probe_trait_that_defines_assoc_item(r.def_id(), assoc_tag, assoc_ident) }); - let Some(bound) = matching_candidates.next() else { - return Err(self.report_unresolved_assoc_item( - all_candidates, - qself, - assoc_tag, - assoc_ident, - span, - constraint, - )); - }; - debug!(?bound); - - if let Some(bound2) = matching_candidates.next() { - debug!(?bound2); - - let assoc_kind_str = errors::assoc_tag_str(assoc_tag); - let qself_str = qself.to_string(tcx); - let mut err = self.dcx().create_err(crate::errors::AmbiguousAssocItem { - span, - assoc_kind: assoc_kind_str, - assoc_ident, - qself: &qself_str, - }); - // Provide a more specific error code index entry for equality bindings. - err.code( - if let Some(constraint) = constraint - && let hir::AssocItemConstraintKind::Equality { .. } = constraint.kind - { - E0222 - } else { - E0221 - }, - ); - - // FIXME(#97583): Print associated item bindings properly (i.e., not as equality - // predicates!). - // FIXME: Turn this into a structured, translatable & more actionable suggestion. - let mut where_bounds = vec![]; - for bound in [bound, bound2].into_iter().chain(matching_candidates) { - let bound_id = bound.def_id(); - let bound_span = tcx - .associated_items(bound_id) - .find_by_ident_and_kind(tcx, assoc_ident, assoc_tag, 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_ident}` from `{}`", bound.print_trait_sugared(),), - ); - if let Some(constraint) = constraint { - match constraint.kind { - hir::AssocItemConstraintKind::Equality { term } => { - let term: ty::Term<'_> = match term { - hir::Term::Ty(ty) => self.lower_ty(ty).into(), - hir::Term::Const(ct) => { - self.lower_const_arg(ct, FeedConstTy::No).into() - } - }; - if term.references_error() { - continue; - } - // FIXME(#97583): This isn't syntactically well-formed! - where_bounds.push(format!( - " T: {trait}::{assoc_ident} = {term}", - trait = bound.print_only_trait_path(), - )); - } - // FIXME: Provide a suggestion. - hir::AssocItemConstraintKind::Bound { bounds: _ } => {} - } - } else { - err.span_suggestion_verbose( - span.with_hi(assoc_ident.span.lo()), - "use fully-qualified syntax to disambiguate", - format!("<{qself_str} as {}>::", bound.print_only_trait_path()), - Applicability::MaybeIncorrect, - ); - } - } else { - let trait_ = - tcx.short_string(bound.print_only_trait_path(), err.long_ty_path()); - err.note(format!( - "associated {assoc_kind_str} `{assoc_ident}` could derive from `{trait_}`", - )); - } - } - if !where_bounds.is_empty() { - err.help(format!( - "consider introducing a new type parameter `T` and adding `where` constraints:\ - \n where\n T: {qself_str},\n{}", - where_bounds.join(",\n"), - )); - let reported = err.emit(); - return Err(reported); - } - err.emit(); + ProbeBoundCandidates { + all_candidates: all_candidates().collect(), + matching_candidates: matching_candidates.collect(), } - - Ok(bound) } /// Lower a [type-relative](hir::QPath::TypeRelative) path in type position to a type. @@ -1266,6 +1307,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { debug!(%self_ty, ?segment.ident); let tcx = self.tcx(); + let mut candidates = vec![]; + // Check if we have an enum variant or an inherent associated type. let mut variant_def_id = None; if let Some(adt_def) = self.probe_adt(span, self_ty) { @@ -1296,19 +1339,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } // FIXME(inherent_associated_types, #106719): Support self types other than ADTs. - if let Some((did, args)) = self.probe_inherent_assoc_item( + let inherent_candidates = self.assemble_iat_candidates( segment, adt_def.did(), self_ty, qpath_hir_id, span, mode.assoc_tag(), - )? { - return Ok(TypeRelativePath::AssocItem(did, args)); - } + ); + candidates + .extend(inherent_candidates.into_iter().map(|cand| (cand.impl_, cand.assoc_item))); } - let (item_def_id, bound) = self.resolve_type_relative_path( + let type_relative_candidates = self.assemble_type_relative_path_candidates( self_ty, hir_self_ty, mode.assoc_tag(), @@ -1316,45 +1359,56 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { qpath_hir_id, span, variant_def_id, - )?; - - let (item_def_id, args) = self.lower_assoc_item_path(span, item_def_id, segment, bound)?; - - if let Some(variant_def_id) = variant_def_id { - tcx.node_span_lint(AMBIGUOUS_ASSOCIATED_ITEMS, qpath_hir_id, span, |lint| { - lint.primary_message("ambiguous associated item"); - let mut could_refer_to = |kind: DefKind, def_id, also| { - let note_msg = format!( - "`{}` could{} refer to the {} defined here", - segment.ident, - also, - tcx.def_kind_descr(kind, def_id) - ); - lint.span_note(tcx.def_span(def_id), note_msg); - }; - - could_refer_to(DefKind::Variant, variant_def_id, ""); - could_refer_to(mode.def_kind(), item_def_id, " also"); - - lint.span_suggestion( - span, - "use fully-qualified syntax", - format!( - "<{} as {}>::{}", - self_ty, - tcx.item_name(bound.def_id()), - segment.ident - ), - Applicability::MachineApplicable, - ); - }); - } - - Ok(TypeRelativePath::AssocItem(item_def_id, args)) + ); + todo!() + + // let (item_def_id, bound) = self.resolve_type_relative_path( + // self_ty, + // hir_self_ty, + // mode.assoc_tag(), + // segment, + // qpath_hir_id, + // span, + // variant_def_id, + // )?; + + // let (item_def_id, args) = self.lower_assoc_item_path(span, item_def_id, segment, bound)?; + + // if let Some(variant_def_id) = variant_def_id { + // tcx.node_span_lint(AMBIGUOUS_ASSOCIATED_ITEMS, qpath_hir_id, span, |lint| { + // lint.primary_message("ambiguous associated item"); + // let mut could_refer_to = |kind: DefKind, def_id, also| { + // let note_msg = format!( + // "`{}` could{} refer to the {} defined here", + // segment.ident, + // also, + // tcx.def_kind_descr(kind, def_id) + // ); + // lint.span_note(tcx.def_span(def_id), note_msg); + // }; + + // could_refer_to(DefKind::Variant, variant_def_id, ""); + // could_refer_to(mode.def_kind(), item_def_id, " also"); + + // lint.span_suggestion( + // span, + // "use fully-qualified syntax", + // format!( + // "<{} as {}>::{}", + // self_ty, + // tcx.item_name(bound.def_id()), + // segment.ident + // ), + // Applicability::MachineApplicable, + // ); + // }); + // } + + // Ok(TypeRelativePath::AssocItem(item_def_id, args)) } /// Resolve a [type-relative](hir::QPath::TypeRelative) (and type-level) path. - fn resolve_type_relative_path( + fn assemble_type_relative_path_candidates( &self, self_ty: Ty<'tcx>, hir_self_ty: &'tcx hir::Ty<'tcx>, @@ -1363,7 +1417,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { qpath_hir_id: HirId, span: Span, variant_def_id: Option, - ) -> Result<(DefId, ty::PolyTraitRef<'tcx>), ErrorGuaranteed> { + ) -> TypeRelativePathCandidates { let tcx = self.tcx(); let self_ty_res = match hir_self_ty.kind { @@ -1372,7 +1426,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }; // Find the type of the assoc item, and the trait where the associated item is declared. - let bound = match (self_ty.kind(), self_ty_res) { + match (self_ty.kind(), self_ty_res) { (_, Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. }) => { // `Self` in an impl of a trait -- we have a concrete self type and a // trait reference. @@ -1391,7 +1445,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { segment.ident, span, None, - )? + ) } ( &ty::Param(_), @@ -1402,29 +1456,31 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { assoc_tag, segment.ident, span, - )?, + ), _ => { - return Err(self.report_unresolved_type_relative_path( - self_ty, - hir_self_ty, - assoc_tag, - segment.ident, - qpath_hir_id, - span, - variant_def_id, - )); + // FIXME(unresolved_aliases): error reporting? + TypeRelativePathCandidates { candidates: vec![] } + // return Err(self.report_unresolved_type_relative_path( + // self_ty, + // hir_self_ty, + // assoc_tag, + // segment.ident, + // qpath_hir_id, + // span, + // variant_def_id, + // )); } - }; + } - let assoc_item = self - .probe_assoc_item(segment.ident, assoc_tag, qpath_hir_id, span, bound.def_id()) - .expect("failed to find associated item"); + // let assoc_item = self + // .probe_assoc_item(segment.ident, assoc_tag, qpath_hir_id, span, bound.def_id()) + // .expect("failed to find associated item"); - Ok((assoc_item.def_id, bound)) + // Ok((assoc_item.def_id, bound)) } /// Search for inherent associated items for use at the type level. - fn probe_inherent_assoc_item( + fn assemble_iat_candidates( &self, segment: &hir::PathSegment<'tcx>, adt_did: DefId, @@ -1432,7 +1488,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { block: HirId, span: Span, assoc_tag: ty::AssocTag, - ) -> Result)>, ErrorGuaranteed> { + ) -> Vec { let tcx = self.tcx(); if !tcx.features().inherent_associated_types() { @@ -1444,19 +1500,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // trait solver), IATs can lead to cycle errors (#108491) which mask the // feature-gate error, needlessly confusing users who use IATs by accident // (#113265). - ty::AssocTag::Type => return Ok(None), - ty::AssocTag::Const => { - // We also gate the mgca codepath for type-level uses of inherent consts - // with the inherent_associated_types feature gate since it relies on the - // same machinery and has similar rough edges. - return Err(feature_err( - &tcx.sess, - sym::inherent_associated_types, - span, - "inherent associated types are unstable", - ) - .emit()); - } + ty::AssocTag::Type | ty::AssocTag::Const => return vec![], ty::AssocTag::Fn => unreachable!(), } } @@ -1475,39 +1519,42 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let (applicable_candidates, fulfillment_errors) = self.select_inherent_assoc_candidates(span, self_ty, candidates.clone()); - let InherentAssocCandidate { impl_, assoc_item, scope: def_scope } = - match &applicable_candidates[..] { - &[] => Err(self.report_unresolved_inherent_assoc_item( - name, - self_ty, - candidates, - fulfillment_errors, - span, - assoc_tag, - )), - - &[applicable_candidate] => Ok(applicable_candidate), - - &[_, ..] => Err(self.report_ambiguous_inherent_assoc_item( - name, - candidates.into_iter().map(|cand| cand.assoc_item).collect(), - span, - )), - }?; - - self.check_assoc_item(assoc_item, name, def_scope, block, span); + // let InherentAssocCandidate { impl_, assoc_item, scope: def_scope } = + // match &applicable_candidates[..] { + // &[] => Err(self.report_unresolved_inherent_assoc_item( + // name, + // self_ty, + // candidates, + // fulfillment_errors, + // span, + // assoc_tag, + // )), + + // &[applicable_candidate] => Ok(applicable_candidate), + + // &[_, ..] => Err(self.report_ambiguous_inherent_assoc_item( + // name, + // candidates.into_iter().map(|cand| cand.assoc_item).collect(), + // span, + // )), + // }?; + + // FIXME(unresolved_aliases): Check we resolve to something accessible + // self.check_assoc_item(assoc_item, name, def_scope, block, span); // FIXME(fmease): Currently creating throwaway `parent_args` to please // `lower_generic_args_of_assoc_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.lower_generic_args_of_assoc_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())), - ); + // let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_); + // let args = self.lower_generic_args_of_assoc_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())), + // ); + + // Ok(Some((assoc_item, args))) - Ok(Some((assoc_item, args))) + applicable_candidates } /// Given name and kind search for the assoc item in the provided scope and check if it's accessible[^1]. diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index ea62461ebeb60..636f3d02eae0d 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -231,6 +231,10 @@ impl EraseType for (&'_ T0, Result<(), ErrorGuaranteed>) { type Result = [u8; size_of::<(&'static (), Result<(), ErrorGuaranteed>)>()]; } +impl EraseType for crate::ty::UnresolvedAliasCandidates<'_> { + type Result = [u8; size_of::>()]; +} + macro_rules! trivial { ($($ty:ty),+ $(,)?) => { $( diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 7bd8a0525a2cf..8e241ee5d662c 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2715,6 +2715,14 @@ rustc_queries! { /// Returns the set of sanitizers that is explicitly disabled for this def. query disabled_sanitizers_for(key: LocalDefId) -> SanitizerSet { desc { |tcx| "checking what set of sanitizers are enabled on `{}`", tcx.def_path_str(key) } + } + + query candidates_for_unresolved_alias(key: DefId) -> ty::UnresolvedAliasCandidates<'tcx> { + desc { |tcx| + "computing candidates for unresolved alias: `{}`", + tcx.def_path_str(key), + } + separate_provide_extern feedable } } diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 3f854038651aa..211494ef33757 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -209,7 +209,7 @@ impl<'tcx> Ty<'tcx> { ty::Placeholder(..) => "higher-ranked type".into(), ty::Bound(..) => "bound type variable".into(), ty::Alias(ty::Projection | ty::Inherent, _) => "associated type".into(), - ty::Alias(ty::Free, _) => "type alias".into(), + ty::Alias(ty::Unresolved | ty::Free, _) => "type alias".into(), ty::Param(_) => "type parameter".into(), ty::Alias(ty::Opaque, ..) => "opaque type".into(), } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index a7298af502ef1..6ebe759ec95b0 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2222,3 +2222,9 @@ pub struct DestructuredConst<'tcx> { pub variant: Option, pub fields: &'tcx [ty::Const<'tcx>], } + +#[derive(Copy, Clone, Debug, HashStable)] +pub struct UnresolvedAliasCandidates<'tcx> { + pub name: Symbol, + pub candidates: &'tcx [(DefId, DefId)], +} diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 74caee7336a5f..564d0780439eb 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -800,7 +800,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } } ty::Foreign(def_id) => self.print_def_path(def_id, &[])?, - ty::Alias(ty::Projection | ty::Inherent | ty::Free, ref data) => data.print(self)?, + ty::Alias(ty::Unresolved | ty::Projection | ty::Inherent | ty::Free, ref data) => data.print(self)?, ty::Placeholder(placeholder) => placeholder.print(self)?, ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => { // We use verbose printing in 'NO_QUERIES' mode, to @@ -3121,6 +3121,9 @@ define_print! { p.print_def_path(self.def_id, self.args)?; } } + // FIXME(thispr): lol + ty::AliasTermKind::UnresolvedTy + | ty::AliasTermKind::UnresolvedConst => todo!(), ty::AliasTermKind::FreeTy | ty::AliasTermKind::FreeConst | ty::AliasTermKind::OpaqueTy diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index a7d07adf78f02..4ec43e0517b0f 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -935,6 +935,8 @@ impl<'tcx> TyCtxt<'tcx> { ty::AliasTermKind::OpaqueTy => Some(self.variances_of(def_id)), ty::AliasTermKind::InherentTy | ty::AliasTermKind::InherentConst + | ty::AliasTermKind::UnresolvedTy + | ty::AliasTermKind::UnresolvedConst | ty::AliasTermKind::FreeTy | ty::AliasTermKind::FreeConst | ty::AliasTermKind::UnevaluatedConst diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index a4a8317912a81..97566815b9977 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -703,7 +703,7 @@ where } ty::Alias(kind @ (ty::Projection | ty::Opaque), alias_ty) => (kind, alias_ty), - ty::Alias(ty::Inherent | ty::Free, _) => { + ty::Alias(ty::Unresolved | ty::Inherent | ty::Free, _) => { self.cx().delay_bug(format!("could not normalize {self_ty:?}, it is not WF")); return; } diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index d25e74e73358f..dcb41857879a8 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -49,7 +49,7 @@ where ty::Dynamic(..) | ty::Param(..) - | ty::Alias(ty::Projection | ty::Inherent | ty::Free, ..) + | ty::Alias(ty::Unresolved | ty::Projection | ty::Inherent | ty::Free, ..) | ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) => { diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 93434dce79fd5..92f3e718ba1f7 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -57,6 +57,8 @@ where self.normalize_free_alias(goal) } ty::AliasTermKind::UnevaluatedConst => self.normalize_anon_const(goal), + // FIXME(thispr) + ty::AliasTermKind::UnresolvedTy | ty::AliasTermKind::UnresolvedConst => todo!(), } } @@ -156,6 +158,9 @@ where } } ty::AliasTermKind::OpaqueTy + // FIXME(thispr): are we only handling rigid aliases here? + | ty::AliasTermKind::UnresolvedTy + | ty::AliasTermKind::UnresolvedConst | ty::AliasTermKind::InherentTy | ty::AliasTermKind::InherentConst | ty::AliasTermKind::FreeTy diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index 5a661072bc7ee..01379520d8d19 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -17,6 +17,8 @@ impl<'tcx> Stable<'tcx> for ty::AliasTyKind { fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { match self { ty::Projection => crate::ty::AliasKind::Projection, + // FIXME(thispr): + ty::Unresolved => todo!(), ty::Inherent => crate::ty::AliasKind::Inherent, ty::Opaque => crate::ty::AliasKind::Opaque, ty::Free => crate::ty::AliasKind::Free, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index 7369134420c67..c105a118689fc 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -719,7 +719,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ty::Projection | ty::Inherent => { format!("the associated type `{bound_kind}`") } - ty::Free => format!("the type alias `{bound_kind}`"), + ty::Unresolved | ty::Free => format!("the type alias `{bound_kind}`"), ty::Opaque => format!("the opaque type `{bound_kind}`"), }, }; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index d768e0bf63fba..0695d24f0f66b 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1722,6 +1722,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ty::CoroutineClosure(..) => Some(21), ty::Pat(..) => Some(22), ty::UnsafeBinder(..) => Some(23), + ty::Alias(ty::Unresolved, ..) => Some(24), ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None, } } diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 23b7f55fbbe53..ab9f6b5220efe 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -279,6 +279,8 @@ impl FlagComputation { ty::Alias(kind, data) => { self.add_flags(match kind { + // FIXME(thispr): Add TypeFlags::HAS_TY_UNRESOLVED? + ty::Unresolved => todo!(), ty::Projection => TypeFlags::HAS_TY_PROJECTION, ty::Free => TypeFlags::HAS_TY_FREE_ALIAS, ty::Opaque => TypeFlags::HAS_TY_OPAQUE, diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index b53eb099c4b95..887153021f7e7 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -485,6 +485,7 @@ pub enum AliasTermKind { /// A projection `::AssocType`. /// Can get normalized away if monomorphic enough. ProjectionTy, + UnresolvedTy, /// An associated type in an inherent `impl` InherentTy, /// An opaque type (usually from `impl Trait` in type aliases or function return types) @@ -501,6 +502,7 @@ pub enum AliasTermKind { ProjectionConst, /// A top level const item not part of a trait or impl. FreeConst, + UnresolvedConst, /// An associated const in an inherent `impl` InherentConst, } @@ -512,6 +514,8 @@ impl AliasTermKind { AliasTermKind::ProjectionConst => "associated const", AliasTermKind::InherentTy => "inherent associated type", AliasTermKind::InherentConst => "inherent associated const", + AliasTermKind::UnresolvedTy => "unresolved type alias", + AliasTermKind::UnresolvedConst => "unresolved const alias", AliasTermKind::OpaqueTy => "opaque type", AliasTermKind::FreeTy => "type alias", AliasTermKind::FreeConst => "unevaluated constant", @@ -522,12 +526,14 @@ impl AliasTermKind { pub fn is_type(self) -> bool { match self { AliasTermKind::ProjectionTy + | AliasTermKind::UnresolvedTy | AliasTermKind::InherentTy | AliasTermKind::OpaqueTy | AliasTermKind::FreeTy => true, AliasTermKind::UnevaluatedConst | AliasTermKind::ProjectionConst + | AliasTermKind::UnresolvedConst | AliasTermKind::InherentConst | AliasTermKind::FreeConst => false, } @@ -537,6 +543,7 @@ impl AliasTermKind { impl From for AliasTermKind { fn from(value: ty::AliasTyKind) -> Self { match value { + ty::Unresolved => AliasTermKind::UnresolvedTy, ty::Projection => AliasTermKind::ProjectionTy, ty::Opaque => AliasTermKind::OpaqueTy, ty::Free => AliasTermKind::FreeTy, @@ -606,13 +613,15 @@ impl AliasTerm { pub fn expect_ty(self, interner: I) -> ty::AliasTy { match self.kind(interner) { AliasTermKind::ProjectionTy + | AliasTermKind::UnresolvedTy | AliasTermKind::InherentTy | AliasTermKind::OpaqueTy | AliasTermKind::FreeTy => {} - AliasTermKind::InherentConst + AliasTermKind::ProjectionConst + | AliasTermKind::UnresolvedConst + | AliasTermKind::InherentConst | AliasTermKind::FreeConst - | AliasTermKind::UnevaluatedConst - | AliasTermKind::ProjectionConst => { + | AliasTermKind::UnevaluatedConst => { panic!("Cannot turn `UnevaluatedConst` into `AliasTy`") } } @@ -631,6 +640,11 @@ impl AliasTerm { ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, ) .into(), + AliasTermKind::UnresolvedTy => Ty::new_alias( + interner, + ty::AliasTyKind::Unresolved, + ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, + ).into(), AliasTermKind::InherentTy => Ty::new_alias( interner, ty::AliasTyKind::Inherent, @@ -650,6 +664,7 @@ impl AliasTerm { ) .into(), AliasTermKind::FreeConst + | AliasTermKind::UnresolvedConst | AliasTermKind::InherentConst | AliasTermKind::UnevaluatedConst | AliasTermKind::ProjectionConst => I::Const::new_unevaluated( diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 223230fde9e72..dd2e492db0d92 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -277,6 +277,8 @@ impl Relate for ty::AliasTerm { ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::FreeConst | ty::AliasTermKind::FreeTy + | ty::AliasTermKind::UnresolvedTy + | ty::AliasTermKind::UnresolvedConst | ty::AliasTermKind::InherentTy | ty::AliasTermKind::InherentConst | ty::AliasTermKind::UnevaluatedConst diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index bde506ffd9385..7e8a62acbd0d0 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -42,6 +42,7 @@ pub enum AliasTyKind { /// A projection `::AssocType`. /// Can get normalized away if monomorphic enough. Projection, + Unresolved, /// An associated type in an inherent `impl` Inherent, /// An opaque type (usually from `impl Trait` in type aliases or function return types) @@ -57,6 +58,7 @@ impl AliasTyKind { pub fn descr(self) -> &'static str { match self { AliasTyKind::Projection => "associated type", + AliasTyKind::Unresolved => "unresolved type alias", AliasTyKind::Inherent => "inherent associated type", AliasTyKind::Opaque => "opaque type", AliasTyKind::Free => "type alias",