Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type-directed probing for inherent associated types #105961

Merged
merged 11 commits into from
Feb 20, 2023

Conversation

fmease
Copy link
Member

@fmease fmease commented Dec 20, 2022

When probing for inherent associated types (IATs), equate the Self-type found in the projection with the Self-type of the relevant inherent impl blocks and check if all predicates are satisfied.
Previously, we didn't look at the Self-type or at the bounds and just picked the first inherent impl block containing an associated type with the name we were searching for which is obviously incorrect.

Regarding the implementation, I basically copied what we do during method probing (assemble_inherent_impl_probe, consider_probe). Unfortunately, I had to duplicate a lot of the diagnostic code found in rustc_hir_typeck::method::suggest which we don't have access to in rustc_hir_analysis. Not sure if there is a simple way to unify the error handling. Note that in the future, rustc_hir_analysis::astconv might not actually be the place where we resolve inherent associated types (see #103621 (comment)) but rustc_hir_typeck (?) in which case the duplication may naturally just disappear. While inherent associated constants are currently resolved during "method" probing, I did not find a straightforward way to incorporate IAT lookup into it as types and values (functions & constants) are two separate entities for which distinct code paths are taken.

Fixes #104251 (incl. #104251 (comment)).
Fixes #105305.
Fixes #107468.

@rustbot label T-types F-inherent_associated_types
r? types

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. F-inherent_associated_types `#![feature(inherent_associated_types)]` labels Dec 20, 2022
@fmease fmease force-pushed the iat-type-directed-probing branch 4 times, most recently from d784f44 to 1177252 Compare December 21, 2022 15:10
@bors
Copy link
Contributor

bors commented Jan 9, 2023

☔ The latest upstream changes (presumably #101947) made this pull request unmergeable. Please resolve the merge conflicts.

@fmease
Copy link
Member Author

fmease commented Jan 11, 2023

Unfortunately, I had to duplicate a lot of the diagnostic code found in rustc_hir_typeck::method::suggest which we don't have access to in rustc_hir_analysis. Not sure if there is a simple way to unify the error handling.

One makeshift solution I am thinking of is to make the subset of the error handling code that I need public definitions in rustc_hir_analysis and use it from rustc_hir_typeck to get rid of the duplication. Should I go forward with it?

@jackh726
Copy link
Member

Sorry for the delay here @fmease. I plan on getting to this by the end of the week.

@fmease
Copy link
Member Author

fmease commented Jan 11, 2023

No worries :) Thanks in advance!

let Ok(InferOk { obligations: sub_obligations, value: () }) = infcx
.at(&ObligationCause::dummy(), param_env)
.define_opaque_types(false)
.sup(impl_ty, self_ty)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does method selection use sup? We probably should use eq here, since that's what match_impl does.

Copy link
Member Author

@fmease fmease Jan 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it does use sup but tbh I am not sure why exactly since it is .ignoring_regions(), too, and lifetime subtyping is the only subtyping in Rust's type system meaning eq and sup should behave identical in this situation, right? I can definitely switch to eq but I wish I could understand for what deeper reason the selection code uses sup.

.sup(probe.xform_self_ty, self_ty)

You likely know the following, I am just making sure I understand correctly. As far as I know method probing ignores regions since implementation-wise it uses FnCtxt which stores Inherited whose only public ctor Inherited::build constructs an InferCtxt .ignoring_regions() and since specification-wise regions are erased before codegen and they should not matter for method dispatch.

Copy link
Member Author

@fmease fmease Jan 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I replace .sup with .eq here, it ices (no longer does since I'm now using the provided InferCtxt). Since I'm no longer ignoring_regions()s though, I am still not sure if it's a good idea to switch.

backtrace
thread 'rustc' panicked at 'index out of bounds: the len is 0 but the index is 0', compiler/rustc_infer/src/infer/region_constraints/mod.rs:459:9
stack backtrace:
   0:     0x7f6d278ebac1 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::hef7c34ced48956ed
   1:     0x7f6d27967fbe - core::fmt::write::hd6821393d61dbc78
   2:     0x7f6d27910171 - std::io::Write::write_fmt::h0aae2c130bb43485
   3:     0x7f6d278eb8ea - std::sys_common::backtrace::print::hefc1376ab8e30bd1
   4:     0x7f6d278eca67 - std::panicking::default_hook::{{closure}}::h133538e0d38da3d4
   5:     0x7f6d278ec895 - std::panicking::default_hook::h0f8bde92f9834261
   6:     0x7f6d282873c5 - rustc_driver[748794e2e144500f]::DEFAULT_HOOK::{closure#0}::{closure#0}
   7:     0x7f6d278ecf73 - std::panicking::rust_panic_with_hook::h6563697fa9ccd808
   8:     0x7f6d278e3089 - std::panicking::begin_panic_handler::{{closure}}::ha90000309b42d4bb
   9:     0x7f6d278e2fbc - std::sys_common::backtrace::__rust_end_short_backtrace::h13266d7b6e524bca
  10:     0x7f6d278ecb3a - rust_begin_unwind
  11:     0x7f6d278ca4e3 - core::panicking::panic_fmt::hee5867c2cd98c87f
  12:     0x7f6d278ca652 - core::panicking::panic_bounds_check::h879d026d129b4b6a
  13:     0x7f6d2a4d1938 - <rustc_infer[c33f17b4b4dc7e29]::infer::region_constraints::RegionConstraintCollector>::universe
  14:     0x7f6d2a5032bb - <rustc_infer[c33f17b4b4dc7e29]::infer::InferCtxt>::universe_of_region
  15:     0x7f6d2a43394a - <rustc_infer[c33f17b4b4dc7e29]::infer::combine::Generalizer as rustc_middle[e87e357ae1384561]::ty::relate::TypeRelation>::regions
  16:     0x7f6d2a43bca2 - rustc_middle[e87e357ae1384561]::ty::relate::super_relate_tys::<rustc_infer[c33f17b4b4dc7e29]::infer::combine::Generalizer>
  17:     0x7f6d2a4330cd - <rustc_infer[c33f17b4b4dc7e29]::infer::combine::Generalizer as rustc_middle[e87e357ae1384561]::ty::relate::TypeRelation>::tys
  18:     0x7f6d2a434592 - <rustc_infer[c33f17b4b4dc7e29]::infer::combine::CombineFields>::instantiate
  19:     0x7f6d2a47c80f - <rustc_infer[c33f17b4b4dc7e29]::infer::equate::Equate as rustc_middle[e87e357ae1384561]::ty::relate::TypeRelation>::tys
  20:     0x7f6d2a5511f6 - <rustc_middle[e87e357ae1384561]::ty::subst::GenericArg as rustc_middle[e87e357ae1384561]::ty::relate::Relate>::relate::<rustc_infer[c33f17b4b4dc7e29]::infer::equate::Equate>
  21:     0x7f6d2a57204c - <core[a759e9f1dec68147]::result::Result<rustc_middle[e87e357ae1384561]::ty::subst::GenericArg, rustc_middle[e87e357ae1384561]::ty::error::TypeError> as rustc_type_ir[98cc6c8502f90b82]::InternIteratorElement<rustc_middle[e87e357ae1384561]::ty::subst::GenericArg, &rustc_middle[e87e357ae1384561]::ty::list::List<rustc_middle[e87e357ae1384561]::ty::subst::GenericArg>>>::intern_with::<core[a759e9f1dec68147]::iter::adapters::map::Map<core[a759e9f1dec68147]::iter::adapters::zip::Zip<core[a759e9f1dec68147]::iter::adapters::copied::Copied<core[a759e9f1dec68147]::slice::iter::Iter<rustc_middle[e87e357ae1384561]::ty::subst::GenericArg>>, core[a759e9f1dec68147]::iter::adapters::copied::Copied<core[a759e9f1dec68147]::slice::iter::Iter<rustc_middle[e87e357ae1384561]::ty::subst::GenericArg>>>, rustc_middle[e87e357ae1384561]::ty::relate::relate_substs<rustc_infer[c33f17b4b4dc7e29]::infer::equate::Equate>::{closure#0}>, <rustc_middle[e87e357ae1384561]::ty::context::TyCtxt>::mk_substs<core[a759e9f1dec68147]::iter::adapters::map::Map<core[a759e9f1dec68147]::iter::adapters::zip::Zip<core[a759e9f1dec68147]::iter::adapters::copied::Copied<core[a759e9f1dec68147]::slice::iter::Iter<rustc_middle[e87e357ae1384561]::ty::subst::GenericArg>>, core[a759e9f1dec68147]::iter::adapters::copied::Copied<core[a759e9f1dec68147]::slice::iter::Iter<rustc_middle[e87e357ae1384561]::ty::subst::GenericArg>>>, rustc_middle[e87e357ae1384561]::ty::relate::relate_substs<rustc_infer[c33f17b4b4dc7e29]::infer::equate::Equate>::{closure#0}>>::{closure#0}>
  22:     0x7f6d2a47bac6 - <rustc_infer[c33f17b4b4dc7e29]::infer::equate::Equate as rustc_middle[e87e357ae1384561]::ty::relate::TypeRelation>::relate_item_substs
  23:     0x7f6d2a43af43 - rustc_middle[e87e357ae1384561]::ty::relate::super_relate_tys::<rustc_infer[c33f17b4b4dc7e29]::infer::equate::Equate>
  24:     0x7f6d2a510fc6 - <rustc_infer[c33f17b4b4dc7e29]::infer::InferCtxt>::super_combine_tys::<rustc_infer[c33f17b4b4dc7e29]::infer::equate::Equate>
  25:     0x7f6d2a47c5ce - <rustc_infer[c33f17b4b4dc7e29]::infer::equate::Equate as rustc_middle[e87e357ae1384561]::ty::relate::TypeRelation>::tys
  26:     0x7f6d2889837a - <rustc_infer[c33f17b4b4dc7e29]::infer::InferCtxt>::commit_if_ok::<rustc_infer[c33f17b4b4dc7e29]::infer::InferOk<()>, rustc_middle[e87e357ae1384561]::ty::error::TypeError, <rustc_infer[c33f17b4b4dc7e29]::infer::at::Trace>::eq<rustc_middle[e87e357ae1384561]::ty::Ty>::{closure#0}>
  27:     0x7f6d289d2db1 - <rustc_infer[c33f17b4b4dc7e29]::infer::at::At>::eq::<rustc_middle[e87e357ae1384561]::ty::Ty>
  28:     0x7f6d2894a509 - <dyn rustc_hir_analysis[2dedc18b32354586]::astconv::AstConv>::associated_path_to_ty::{closure#0}
  29:     0x7f6d289499fa - <dyn rustc_hir_analysis[2dedc18b32354586]::astconv::AstConv>::associated_path_to_ty
  30:     0x7f6d2894e1e8 - <dyn rustc_hir_analysis[2dedc18b32354586]::astconv::AstConv>::ast_ty_to_ty_inner
  31:     0x7f6d28657fcf - <rustc_hir_typeck[5384bad6713105a9]::fn_ctxt::FnCtxt>::to_ty
  32:     0x7f6d285febcf - <rustc_hir_typeck[5384bad6713105a9]::gather_locals::GatherLocalsVisitor>::declare
  33:     0x7f6d287c41b3 - rustc_hir[cf8f75e2b7a3e0eb]::intravisit::walk_block::<rustc_hir_typeck[5384bad6713105a9]::gather_locals::GatherLocalsVisitor>
  34:     0x7f6d286ec69d - rustc_hir_typeck[5384bad6713105a9]::check::check_fn
  35:     0x7f6d286d9dac - <rustc_hir_typeck[5384bad6713105a9]::inherited::InheritedBuilder>::enter::<rustc_hir_typeck[5384bad6713105a9]::typeck_with_fallback<rustc_hir_typeck[5384bad6713105a9]::typeck::{closure#0}>::{closure#0}::{closure#1}, &rustc_middle[e87e357ae1384561]::ty::typeck_results::TypeckResults>
  36:     0x7f6d2881336a - rustc_hir_typeck[5384bad6713105a9]::typeck_with_fallback::<rustc_hir_typeck[5384bad6713105a9]::typeck::{closure#0}>
  37:     0x7f6d287399a4 - rustc_hir_typeck[5384bad6713105a9]::typeck
  38:     0x7f6d299a66f4 - rustc_query_system[a641d3afe2b8834a]::query::plumbing::try_execute_query::<rustc_query_impl[2d661b98ef5c64e8]::queries::typeck, rustc_query_impl[2d661b98ef5c64e8]::plumbing::QueryCtxt>
  39:     0x7f6d29a41b20 - rustc_query_system[a641d3afe2b8834a]::query::plumbing::get_query::<rustc_query_impl[2d661b98ef5c64e8]::queries::typeck, rustc_query_impl[2d661b98ef5c64e8]::plumbing::QueryCtxt, rustc_middle[e87e357ae1384561]::dep_graph::dep_node::DepKind>
  40:     0x7f6d297542c8 - <rustc_query_impl[2d661b98ef5c64e8]::Queries as rustc_middle[e87e357ae1384561]::ty::query::QueryEngine>::typeck
  41:     0x7f6d2877c016 - std[6161937930c6e443]::panicking::try::<(), core[a759e9f1dec68147]::panic::unwind_safe::AssertUnwindSafe<rustc_data_structures[ad989cddaa07d642]::sync::par_for_each_in<&[rustc_span[67e7a4497f54abf5]::def_id::LocalDefId], <rustc_middle[e87e357ae1384561]::hir::map::Map>::par_body_owners<rustc_hir_typeck[5384bad6713105a9]::typeck_item_bodies::{closure#0}>::{closure#0}>::{closure#0}::{closure#0}>>
  42:     0x7f6d28811395 - rustc_data_structures[ad989cddaa07d642]::sync::par_for_each_in::<&[rustc_span[67e7a4497f54abf5]::def_id::LocalDefId], <rustc_middle[e87e357ae1384561]::hir::map::Map>::par_body_owners<rustc_hir_typeck[5384bad6713105a9]::typeck_item_bodies::{closure#0}>::{closure#0}>
  43:     0x7f6d28739865 - rustc_hir_typeck[5384bad6713105a9]::typeck_item_bodies
  44:     0x7f6d2996323a - rustc_query_system[a641d3afe2b8834a]::query::plumbing::try_execute_query::<rustc_query_impl[2d661b98ef5c64e8]::queries::typeck_item_bodies, rustc_query_impl[2d661b98ef5c64e8]::plumbing::QueryCtxt>
  45:     0x7f6d29a141ef - rustc_query_system[a641d3afe2b8834a]::query::plumbing::get_query::<rustc_query_impl[2d661b98ef5c64e8]::queries::typeck_item_bodies, rustc_query_impl[2d661b98ef5c64e8]::plumbing::QueryCtxt, rustc_middle[e87e357ae1384561]::dep_graph::dep_node::DepKind>
  46:     0x7f6d29753d8e - <rustc_query_impl[2d661b98ef5c64e8]::Queries as rustc_middle[e87e357ae1384561]::ty::query::QueryEngine>::typeck_item_bodies
  47:     0x7f6d2892e4e8 - <rustc_session[29c6e5af3d515c5e]::session::Session>::time::<(), rustc_hir_analysis[2dedc18b32354586]::check_crate::{closure#7}>
  48:     0x7f6d2889bdae - rustc_hir_analysis[2dedc18b32354586]::check_crate
  49:     0x7f6d283c6e52 - rustc_interface[e7497e78aff66ef4]::passes::analysis
  50:     0x7f6d299a87ca - rustc_query_system[a641d3afe2b8834a]::query::plumbing::try_execute_query::<rustc_query_impl[2d661b98ef5c64e8]::queries::analysis, rustc_query_impl[2d661b98ef5c64e8]::plumbing::QueryCtxt>
  51:     0x7f6d29a41db1 - rustc_query_system[a641d3afe2b8834a]::query::plumbing::get_query::<rustc_query_impl[2d661b98ef5c64e8]::queries::analysis, rustc_query_impl[2d661b98ef5c64e8]::plumbing::QueryCtxt, rustc_middle[e87e357ae1384561]::dep_graph::dep_node::DepKind>
  52:     0x7f6d29735a5e - <rustc_query_impl[2d661b98ef5c64e8]::Queries as rustc_middle[e87e357ae1384561]::ty::query::QueryEngine>::analysis
  53:     0x7f6d2828fb05 - <rustc_interface[e7497e78aff66ef4]::passes::QueryContext>::enter::<rustc_driver[748794e2e144500f]::run_compiler::{closure#1}::{closure#2}::{closure#3}, core[a759e9f1dec68147]::result::Result<(), rustc_errors[aafc41f3c6a3f30f]::ErrorGuaranteed>>
  54:     0x7f6d2829103c - <rustc_interface[e7497e78aff66ef4]::interface::Compiler>::enter::<rustc_driver[748794e2e144500f]::run_compiler::{closure#1}::{closure#2}, core[a759e9f1dec68147]::result::Result<core[a759e9f1dec68147]::option::Option<rustc_interface[e7497e78aff66ef4]::queries::Linker>, rustc_errors[aafc41f3c6a3f30f]::ErrorGuaranteed>>
  55:     0x7f6d2826f966 - rustc_span[67e7a4497f54abf5]::with_source_map::<core[a759e9f1dec68147]::result::Result<(), rustc_errors[aafc41f3c6a3f30f]::ErrorGuaranteed>, rustc_interface[e7497e78aff66ef4]::interface::run_compiler<core[a759e9f1dec68147]::result::Result<(), rustc_errors[aafc41f3c6a3f30f]::ErrorGuaranteed>, rustc_driver[748794e2e144500f]::run_compiler::{closure#1}>::{closure#0}::{closure#0}>
  56:     0x7f6d282933fc - <scoped_tls[535ca24a62cbd8c4]::ScopedKey<rustc_span[67e7a4497f54abf5]::SessionGlobals>>::set::<rustc_interface[e7497e78aff66ef4]::interface::run_compiler<core[a759e9f1dec68147]::result::Result<(), rustc_errors[aafc41f3c6a3f30f]::ErrorGuaranteed>, rustc_driver[748794e2e144500f]::run_compiler::{closure#1}>::{closure#0}, core[a759e9f1dec68147]::result::Result<(), rustc_errors[aafc41f3c6a3f30f]::ErrorGuaranteed>>
  57:     0x7f6d2827c1aa - std[6161937930c6e443]::sys_common::backtrace::__rust_begin_short_backtrace::<rustc_interface[e7497e78aff66ef4]::util::run_in_thread_pool_with_globals<rustc_interface[e7497e78aff66ef4]::interface::run_compiler<core[a759e9f1dec68147]::result::Result<(), rustc_errors[aafc41f3c6a3f30f]::ErrorGuaranteed>, rustc_driver[748794e2e144500f]::run_compiler::{closure#1}>::{closure#0}, core[a759e9f1dec68147]::result::Result<(), rustc_errors[aafc41f3c6a3f30f]::ErrorGuaranteed>>::{closure#0}::{closure#0}, core[a759e9f1dec68147]::result::Result<(), rustc_errors[aafc41f3c6a3f30f]::ErrorGuaranteed>>
  58:     0x7f6d282976ee - std[6161937930c6e443]::panicking::try::<core[a759e9f1dec68147]::result::Result<(), rustc_errors[aafc41f3c6a3f30f]::ErrorGuaranteed>, core[a759e9f1dec68147]::panic::unwind_safe::AssertUnwindSafe<<std[6161937930c6e443]::thread::Builder>::spawn_unchecked_<rustc_interface[e7497e78aff66ef4]::util::run_in_thread_pool_with_globals<rustc_interface[e7497e78aff66ef4]::interface::run_compiler<core[a759e9f1dec68147]::result::Result<(), rustc_errors[aafc41f3c6a3f30f]::ErrorGuaranteed>, rustc_driver[748794e2e144500f]::run_compiler::{closure#1}>::{closure#0}, core[a759e9f1dec68147]::result::Result<(), rustc_errors[aafc41f3c6a3f30f]::ErrorGuaranteed>>::{closure#0}::{closure#0}, core[a759e9f1dec68147]::result::Result<(), rustc_errors[aafc41f3c6a3f30f]::ErrorGuaranteed>>::{closure#1}::{closure#0}>>
  59:     0x7f6d2828c646 - <<std[6161937930c6e443]::thread::Builder>::spawn_unchecked_<rustc_interface[e7497e78aff66ef4]::util::run_in_thread_pool_with_globals<rustc_interface[e7497e78aff66ef4]::interface::run_compiler<core[a759e9f1dec68147]::result::Result<(), rustc_errors[aafc41f3c6a3f30f]::ErrorGuaranteed>, rustc_driver[748794e2e144500f]::run_compiler::{closure#1}>::{closure#0}, core[a759e9f1dec68147]::result::Result<(), rustc_errors[aafc41f3c6a3f30f]::ErrorGuaranteed>>::{closure#0}::{closure#0}, core[a759e9f1dec68147]::result::Result<(), rustc_errors[aafc41f3c6a3f30f]::ErrorGuaranteed>>::{closure#1} as core[a759e9f1dec68147]::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
  60:     0x7f6d279038b8 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::hfe0a9abdbb746703
  61:     0x7f6d278f1877 - std::sys::unix::thread::Thread::new::thread_start::h84bfc89499a70691
  62:     0x7f6d276f78fd - <unknown>
  63:     0x7f6d27779a60 - <unknown>
  64:                0x0 - <unknown>

error: internal compiler error: unexpected panic

note: the compiler unexpectedly panicked. this is a bug.

note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md

note: rustc 1.69.0-dev running on x86_64-unknown-linux-gnu

note: compiler flags: -Z threads=1 -C codegen-units=1 -Z ui-testing -Z simulate-remapped-rust-src-base=/rustc/FAKE_PREFIX -Z translate-remapped-path-to-local-path=no -Z deduplicate-diagnostics=no -C strip=debuginfo -C prefer-dynamic -C rpath -C debuginfo=0

query stack during panic:
#0 [typeck] type-checking `main`
#1 [typeck_item_bodies] type-checking all item bodies
#2 [analysis] running analysis passes on this crate
end of query stack

self.create_substs_for_associated_item(span, assoc_item, segment, adt_substs);
// FIXME(inherent_associated_types): Check if the obligations arising from the
// where-clause & the bounds on the associated type and its parameters hold.
let ty = tcx.bound_type_of(assoc_item).subst(tcx, item_substs);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if astconv should turn this into a ty::Projection with the impl item def id, then let normalization handle projecting it onto the real type and confirming the GAT substitutions. It would fix this comment:

Check if the obligations arising from the where-clause & the bounds on the associated type and its parameters hold.

Copy link
Member Author

@fmease fmease Jan 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That FIXME now has its own issue btw, namely #106722. I can try to implement your suggestion and return a type of kind TyKind::Alias(AliasKind::Projection, AliasTy { … }). I faintly remember trying this before and it lead to ICEs down the line where the compiler wasn't happy that inherent assoc ty projections obviously lacked a trait reference. The docs of AliasTy.def_id confirm this: “The DefId of the TraitItem […] if this is a projection”. Let's see if I can find another way. I wonder if rust-lang/compiler-team#504 is relevant here (to some extend I mean since we are talking about assoc tys here not top-level type aliases).

Should I attempt this in this PR though, I wonder? I want to keep things “minimal” to make life easier for reviewers and since I don't even know if the general disposition for this PR is merging or closing as the implementation is not quite clean (yet).

Copy link
Member Author

@fmease fmease Jan 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think we are in need of a new AliasKind::InherentProjection (modulo naming)? I am not deeply familiar with the inner workings of the type system yet but as far as I understand at some point in the future we do need to map polymorphic inherent associated types to some form of placeholder projection types for lazy normalization & proper unification for them and to finally pave the way towards the long-awaited stabilization of IATs. Did I get that right?

Copy link
Member Author

@fmease fmease Jan 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think we are in need of a new AliasKind::InherentProjection (modulo naming)?

I am currently investigating this approach.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would be good as a followup.

@rustbot rustbot added the T-types Relevant to the types team, which will review and decide on the PR/issue. label Jan 13, 2023
@bors
Copy link
Contributor

bors commented Jan 14, 2023

☔ The latest upstream changes (presumably #106822) made this pull request unmergeable. Please resolve the merge conflicts.

Copy link
Member

@jackh726 jackh726 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry that this has taken so long :/

I think my comments here could be added as FIXMEs and we could land this mostly as-is. But of course, address as much as you'd like/can.

Comment on lines 30 to 34
let _: Select<String>::Projection = false;
let _: Select<u8>::Projection = ();

let _: Choose<NonCopy>::Result = ();
let _: Choose<&str>::Result = vec!["..."];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For followup work: it would be nice to see tests where we don't have a concrete type, but instead something from the environment.

Copy link
Member Author

@fmease fmease Jan 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added two tests to make sure we use the correct ParamEnv. The first one is in fn parameterized in dispatch-on-self-type-0.rs which is check-pass and the second one is not-found-unsatisfied-bounds-1.rs which is check-fail. I did in fact not use the correct ParamEnv before. Now I use the environment of block.owner instead of the one of the impl block. Let me know if you'd like to see more ParamEnv tests (in a follow-up PR maybe).

Comment on lines 2293 to 2309
// Evaluate those obligations to see if they might possibly hold.
for o in candidate_obligations {
let o = infcx.resolve_vars_if_possible(o);
if !infcx.predicate_may_hold(&o) {
matches = false;
unsatisfied_predicates.push(o.predicate);
}
}

// Evaluate those obligations to see if they might possibly hold.
for o in sub_obligations {
let o = infcx.resolve_vars_if_possible(o);
if !infcx.predicate_may_hold(&o) {
matches = false;
unsatisfied_predicates.push(o.predicate);
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I imagine it might make more sense to use an ObligationCtxt here. Just register all the obligations and then call select_where_possible (maybe? would have to think a bit harder about it).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It also has helpful operations for the some of the above.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've switched to using an ObligationCtxt as suggested.

Comment on lines 2330 to 2307
Err(self.complain_about_inherent_assoc_type_not_found(
name,
self_ty,
&candidates.into_iter().map(|(impl_, _)| impl_).collect::<Vec<_>>(),
unsatisfied_predicates,
span,
))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it helpful to combine all unsatisfied predicates?

Copy link
Member Author

@fmease fmease Jan 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it is not. Not sure what I was thinking. Fixed in the latest commit.

self.create_substs_for_associated_item(span, assoc_item, segment, adt_substs);
// FIXME(inherent_associated_types): Check if the obligations arising from the
// where-clause & the bounds on the associated type and its parameters hold.
let ty = tcx.bound_type_of(assoc_item).subst(tcx, item_substs);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would be good as a followup.

@bors
Copy link
Contributor

bors commented Jan 28, 2023

☔ The latest upstream changes (presumably #107400) made this pull request unmergeable. Please resolve the merge conflicts.

@fmease
Copy link
Member Author

fmease commented Jan 30, 2023

I've addressed the review comments either as a fix or as a FIXME for follow-up PRs. I've not squashed the commits for ease of review but I can do so after approval.

I am no longer sure if it's safe to ignore_regions here since I am conflating the probe and the confirmation phase. I have to think about this but it shouldn't be a blocker (?). I am now using the InferCtxt provided by AstConv which does not ignore regions.

@fmease fmease requested a review from jackh726 January 30, 2023 16:50
&candidates.into_iter().map(|(impl_, _)| impl_).collect::<Vec<_>>(),
unsatisfied_predicates,
span,
))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we error here? What happens if there is an associated type through a trait?

Copy link
Member Author

@fmease fmease Jan 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, we should probably not eagerly error here. Returning early yields a better different error message (compared to master). In terms of correctness, we wouldn't be able to shadow any associated types defined in trait impls, since they would be ambiguous anyway. Right? Since in such cases, the Self-type would always refer to a concrete type constructor (and not to a type parameter for example).

// pseudo ui test

#![feature(inherent_associated_types)]
#![allow(incomplete_features)]

struct S<T>(T);

trait Tr {
    type Pr;
    const PR: Self::Pr;
}

impl<T> Tr for S<T> {
    type Pr = ();
    const PR: () = ();
}

#[cfg(branch_is_fmease_iat_type_directed_probing)]
impl S<()> {
    type Pr = i32;
    const PR: Self::Pr = 10;
}

fn main() {
    let _: () = S::<bool>::PR; // PASS (pass through)
    let _: S::<bool>::Pr = ();
    //[master]~^ ERROR[E0223] ambiguous associated type
    //[fmease:iat-type-directed-probing]~^^ ERROR associated type […] not found
}

Do you consider this a diagnostic regression?

[@]rustbot author
@rustbot reviewer

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jan 30, 2023
Copy link
Member

@jackh726 jackh726 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few comments. I wouldn't mind leaving them as FIXMEs for now though.

Comment on lines +1 to +20
error: the associated type `X` exists for `S<Featureless, Featureless>`, but its trait bounds were not satisfied
--> $DIR/not-found-unsatisfied-bounds-in-multiple-impls.rs:19:43
|
LL | struct S<A, B>(A, B);
| -------------- associated item `X` not found for this struct
LL | struct Featureless;
| ------------------
| |
| doesn't satisfy `Featureless: One`
| doesn't satisfy `Featureless: Two`
...
LL | let _: S::<Featureless, Featureless>::X;
| ^ associated type cannot be referenced on `S<Featureless, Featureless>` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`Featureless: One`
`Featureless: Two`

error: aborting due to previous error

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, this is a good test to showcase the current problem with fulfillment_errors being a Vec<FulfillmentError>.

Ideally, this error should point to this impl impl<T: One> S<Featureless, T>, then say that Featureless: One is not satisfied. Then point at this impl impl<T: Two> S<T, Featureless> and say that Featureless: Two is not satisfied.

Right now, you aren't pointing to the impls and are conflating what bounds must be satisfied for and individual impl to apply.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. However, this shouldn't be hard to fix. I basically have to copy over the changes made in #106702. When I opened my PR, I copied over the now outdated suggestion code. Before #106702, the equivalent code with assoc fns / consts had the same diagnostic. See for yourself: Playground (stable), playground (nightly).

I can update the diagnostic code once I've fixed the confirmation code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, exactly the same thing actually!

impl<T: Two> S<T, Featureless> {
type X = String;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, re coherence, if you added both impl One for Featureless and impl Two for Featureless, then both of these inherent impls could apply. Without the associated types, this is fine, but we do in fact complain in inherent_impls_overlap.

}
};

if fulfillment_errors.is_empty() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would make more sense to pass a Vec<(DefId, (DefId, DefId), Option<Vec<FulfillmentError>>)>.

I see why checking if for is_empty() here is okay: basically, this is the case where all the Self types are different (which should be obvious by just enumerating the candidates). This could be the "simple path": if all the candidates have no fulfillment errors -> list (as is done now).

Otherwise, for each candidate, list the unsatisfied bounds.

Comment on lines 2287 to 2288
// FIXME(inherent_associated_types): To fully *confirm* the *probed* candidate,
// we still need to register region obligations for regionck to prove/disprove.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should create new fresh item substs, then relate to the self ty (as done before).

But this can be left to another time.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a FIXME though

@jackh726
Copy link
Member

There is obviously followup work for this, but given it's an unstable feature, I'm fine with these being FIXMEs for now.

Sorry for the review latency here. Thanks for addressing the reviews.

@bors r+

@bors
Copy link
Contributor

bors commented Feb 19, 2023

📌 Commit f2253da has been approved by jackh726

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Feb 19, 2023
@bors
Copy link
Contributor

bors commented Feb 20, 2023

⌛ Testing commit f2253da with merge 7b55296...

@bors
Copy link
Contributor

bors commented Feb 20, 2023

☀️ Test successful - checks-actions
Approved by: jackh726
Pushing 7b55296 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Feb 20, 2023
@bors bors merged commit 7b55296 into rust-lang:master Feb 20, 2023
@rustbot rustbot added this to the 1.69.0 milestone Feb 20, 2023
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (7b55296): comparison URL.

Overall result: no relevant changes - no action needed

@rustbot label: -perf-regression

Instruction count

This benchmark run did not return any relevant results for this metric.

Max RSS (memory usage)

This benchmark run did not return any relevant results for this metric.

Cycles

This benchmark run did not return any relevant results for this metric.

@fmease fmease deleted the iat-type-directed-probing branch February 20, 2023 12:27
compiler-errors added a commit to compiler-errors/rust that referenced this pull request May 8, 2023
…compiler-errors

Introduce `AliasKind::Inherent` for inherent associated types

Allows us to check (possibly generic) inherent associated types for well-formedness.
Type inference now also works properly.

Follow-up to rust-lang#105961. Supersedes rust-lang#108430.
Fixes rust-lang#106722.
Fixes rust-lang#108957.
Fixes rust-lang#109768.
Fixes rust-lang#109789.
Fixes rust-lang#109790.

~Not to be merged before rust-lang#108860 (`AliasKind::Weak`).~

CC `@jackh726`
r? `@compiler-errors`

`@rustbot` label T-types F-inherent_associated_types
flip1995 pushed a commit to flip1995/rust that referenced this pull request May 20, 2023
…compiler-errors

Introduce `AliasKind::Inherent` for inherent associated types

Allows us to check (possibly generic) inherent associated types for well-formedness.
Type inference now also works properly.

Follow-up to rust-lang#105961. Supersedes rust-lang#108430.
Fixes rust-lang#106722.
Fixes rust-lang#108957.
Fixes rust-lang#109768.
Fixes rust-lang#109789.
Fixes rust-lang#109790.

~Not to be merged before rust-lang#108860 (`AliasKind::Weak`).~

CC `@jackh726`
r? `@compiler-errors`

`@rustbot` label T-types F-inherent_associated_types
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
F-inherent_associated_types `#![feature(inherent_associated_types)]` merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
8 participants