-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Conversation
d784f44
to
1177252
Compare
☔ The latest upstream changes (presumably #101947) made this pull request unmergeable. Please resolve the merge conflicts. |
fb03d8e
to
35f5315
Compare
One makeshift solution I am thinking of is to make the subset of the error handling code that I need public definitions in |
35f5315
to
d366229
Compare
Sorry for the delay here @fmease. I plan on getting to this by the end of the week. |
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) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
☔ The latest upstream changes (presumably #106822) made this pull request unmergeable. Please resolve the merge conflicts. |
d366229
to
5094a8e
Compare
There was a problem hiding this 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.
let _: Select<String>::Projection = false; | ||
let _: Select<u8>::Projection = (); | ||
|
||
let _: Choose<NonCopy>::Result = (); | ||
let _: Choose<&str>::Result = vec!["..."]; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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).
// 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); | ||
} | ||
} |
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
Err(self.complain_about_inherent_assoc_type_not_found( | ||
name, | ||
self_ty, | ||
&candidates.into_iter().map(|(impl_, _)| impl_).collect::<Vec<_>>(), | ||
unsatisfied_predicates, | ||
span, | ||
)) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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.
☔ The latest upstream changes (presumably #107400) made this pull request unmergeable. Please resolve the merge conflicts. |
5094a8e
to
120e80b
Compare
I've addressed the review comments either as a fix or as a
|
&candidates.into_iter().map(|(impl_, _)| impl_).collect::<Vec<_>>(), | ||
unsatisfied_predicates, | ||
span, | ||
)) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
4f72470
to
422b3fd
Compare
There was a problem hiding this 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.
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 | ||
|
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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; | ||
} | ||
|
There was a problem hiding this comment.
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() { |
There was a problem hiding this comment.
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.
// FIXME(inherent_associated_types): To fully *confirm* the *probed* candidate, | ||
// we still need to register region obligations for regionck to prove/disprove. |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
422b3fd
to
f2253da
Compare
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+ |
☀️ Test successful - checks-actions |
Finished benchmarking commit (7b55296): comparison URL. Overall result: no relevant changes - no action needed@rustbot label: -perf-regression Instruction countThis 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. CyclesThis benchmark run did not return any relevant results for this metric. |
…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
…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
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 inrustc_hir_typeck::method::suggest
which we don't have access to inrustc_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)) butrustc_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