Skip to content

Commit 54a8a1d

Browse files
committed
Auto merge of #146885 - lcnr:method-selection-opaques, r=BoxyUwU
support opaque types in method selection See my notes in https://hackmd.io/4ILASx3mQ3u_gW9r1JyqCw. This PR builds on #145993 and allows not-yet defined opaque types as self types in the `method_autoderef_chain`. E.g. for `Box<impl Deref<impl Foo>>` this results in the autoderef chain `Box<impl Deref> -> ?deref_hidden_ty -> ?foo_hidden_ty`. Method selection stays ambiguous if the final autoderef step is still an infer var unless that var is an opaque. TODO: treating opaques as rigid jank. r? `@BoxyUwU`
2 parents a885811 + c2e39c2 commit 54a8a1d

File tree

64 files changed

+647
-291
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+647
-291
lines changed

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,8 +1633,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16331633
expected: Expectation<'tcx>,
16341634
) -> Ty<'tcx> {
16351635
let rcvr_t = self.check_expr(rcvr);
1636-
// no need to check for bot/err -- callee does that
1637-
let rcvr_t = self.structurally_resolve_type(rcvr.span, rcvr_t);
1636+
let rcvr_t = self.try_structurally_resolve_type(rcvr.span, rcvr_t);
16381637

16391638
match self.lookup_method(rcvr_t, segment, segment.ident.span, expr, rcvr, args) {
16401639
Ok(method) => {

compiler/rustc_hir_typeck/src/method/confirm.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
172172
// Commit the autoderefs by calling `autoderef` again, but this
173173
// time writing the results into the various typeck results.
174174
let mut autoderef = self.autoderef(self.call_expr.span, unadjusted_self_ty);
175-
let Some((ty, n)) = autoderef.nth(pick.autoderefs) else {
175+
let Some((mut target, n)) = autoderef.nth(pick.autoderefs) else {
176176
return Ty::new_error_with_message(
177177
self.tcx,
178178
DUMMY_SP,
@@ -182,8 +182,6 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
182182
assert_eq!(n, pick.autoderefs);
183183

184184
let mut adjustments = self.adjust_steps(&autoderef);
185-
let mut target = self.structurally_resolve_type(autoderef.span(), ty);
186-
187185
match pick.autoref_or_ptr_adjustment {
188186
Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl, unsize }) => {
189187
let region = self.next_region_var(RegionVariableOrigin::Autoref(self.span));

compiler/rustc_hir_typeck/src/method/probe.rs

Lines changed: 230 additions & 37 deletions
Large diffs are not rendered by default.

compiler/rustc_infer/src/infer/canonical/query_response.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,29 @@ impl<'tcx> InferCtxt<'tcx> {
8585
where
8686
T: Debug + TypeFoldable<TyCtxt<'tcx>>,
8787
{
88+
// While we ignore region constraints and pending obligations,
89+
// we do return constrained opaque types to avoid unconstrained
90+
// inference variables in the response. This is important as we want
91+
// to check that opaques in deref steps stay unconstrained.
92+
//
93+
// This doesn't handle the more general case for non-opaques as
94+
// ambiguous `Projection` obligations have same the issue.
95+
let opaque_types = if self.next_trait_solver() {
96+
self.inner
97+
.borrow_mut()
98+
.opaque_type_storage
99+
.iter_opaque_types()
100+
.map(|(k, v)| (k, v.ty))
101+
.collect()
102+
} else {
103+
vec![]
104+
};
105+
88106
self.canonicalize_response(QueryResponse {
89107
var_values: inference_vars,
90108
region_constraints: QueryRegionConstraints::default(),
91109
certainty: Certainty::Proven, // Ambiguities are OK!
92-
opaque_types: vec![],
110+
opaque_types,
93111
value: answer,
94112
})
95113
}

compiler/rustc_middle/src/arena.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ macro_rules! arena_types {
109109
rustc_middle::ty::EarlyBinder<'tcx, rustc_middle::ty::Ty<'tcx>>
110110
>,
111111
[] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<rustc_middle::ty::TyCtxt<'tcx>>,
112-
[] predefined_opaques_in_body: rustc_middle::traits::solve::PredefinedOpaquesData<rustc_middle::ty::TyCtxt<'tcx>>,
113112
[decode] doc_link_resolutions: rustc_hir::def::DocLinkResMap,
114113
[] stripped_cfg_items: rustc_hir::attrs::StrippedCfgItem,
115114
[] mod_child: rustc_middle::metadata::ModChild,

compiler/rustc_middle/src/query/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ use crate::query::plumbing::{
124124
};
125125
use crate::traits::query::{
126126
CanonicalAliasGoal, CanonicalDropckOutlivesGoal, CanonicalImpliedOutlivesBoundsGoal,
127-
CanonicalPredicateGoal, CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal,
127+
CanonicalMethodAutoderefStepsGoal, CanonicalPredicateGoal, CanonicalTypeOpAscribeUserTypeGoal,
128128
CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal, DropckConstraint,
129129
DropckOutlivesResult, MethodAutoderefStepsResult, NoSolution, NormalizationResult,
130130
OutlivesBound,
@@ -2559,9 +2559,9 @@ rustc_queries! {
25592559
}
25602560

25612561
query method_autoderef_steps(
2562-
goal: CanonicalTyGoal<'tcx>
2562+
goal: CanonicalMethodAutoderefStepsGoal<'tcx>
25632563
) -> MethodAutoderefStepsResult<'tcx> {
2564-
desc { "computing autoderef types for `{}`", goal.canonical.value.value }
2564+
desc { "computing autoderef types for `{}`", goal.canonical.value.value.self_ty }
25652565
}
25662566

25672567
/// Used by `-Znext-solver` to compute proof trees.

compiler/rustc_middle/src/traits/query.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_span::Span;
1010

1111
use crate::error::DropCheckOverflow;
1212
use crate::infer::canonical::{Canonical, CanonicalQueryInput, QueryResponse};
13+
use crate::traits::solve;
1314
pub use crate::traits::solve::NoSolution;
1415
use crate::ty::{self, GenericArg, Ty, TyCtxt};
1516

@@ -67,7 +68,16 @@ pub mod type_op {
6768
pub type CanonicalAliasGoal<'tcx> =
6869
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, ty::AliasTy<'tcx>>>;
6970

70-
pub type CanonicalTyGoal<'tcx> = CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>;
71+
pub type CanonicalMethodAutoderefStepsGoal<'tcx> =
72+
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, MethodAutoderefSteps<'tcx>>>;
73+
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)]
74+
pub struct MethodAutoderefSteps<'tcx> {
75+
/// The list of opaque types currently in the storage.
76+
///
77+
/// Only used by the new solver for now.
78+
pub predefined_opaques_in_body: solve::PredefinedOpaques<'tcx>,
79+
pub self_ty: Ty<'tcx>,
80+
}
7181

7282
pub type CanonicalPredicateGoal<'tcx> =
7383
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>>;
@@ -144,6 +154,7 @@ impl<'tcx> FromIterator<DropckConstraint<'tcx>> for DropckConstraint<'tcx> {
144154
#[derive(Debug, HashStable)]
145155
pub struct CandidateStep<'tcx> {
146156
pub self_ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
157+
pub self_ty_is_opaque: bool,
147158
pub autoderefs: usize,
148159
/// `true` if the type results from a dereference of a raw pointer.
149160
/// when assembling candidates, we include these steps, but not when

compiler/rustc_middle/src/traits/solve.rs

Lines changed: 2 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_type_ir as ir;
44
pub use rustc_type_ir::solve::*;
55

66
use crate::ty::{
7-
self, FallibleTypeFolder, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor,
7+
self, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor,
88
try_visit,
99
};
1010

@@ -15,16 +15,7 @@ pub type CandidateSource<'tcx> = ir::solve::CandidateSource<TyCtxt<'tcx>>;
1515
pub type CanonicalInput<'tcx, P = ty::Predicate<'tcx>> = ir::solve::CanonicalInput<TyCtxt<'tcx>, P>;
1616
pub type CanonicalResponse<'tcx> = ir::solve::CanonicalResponse<TyCtxt<'tcx>>;
1717

18-
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, HashStable)]
19-
pub struct PredefinedOpaques<'tcx>(pub(crate) Interned<'tcx, PredefinedOpaquesData<TyCtxt<'tcx>>>);
20-
21-
impl<'tcx> std::ops::Deref for PredefinedOpaques<'tcx> {
22-
type Target = PredefinedOpaquesData<TyCtxt<'tcx>>;
23-
24-
fn deref(&self) -> &Self::Target {
25-
&self.0
26-
}
27-
}
18+
pub type PredefinedOpaques<'tcx> = &'tcx ty::List<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>;
2819

2920
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, HashStable)]
3021
pub struct ExternalConstraints<'tcx>(
@@ -93,35 +84,3 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
9384
self.normalization_nested_goals.visit_with(visitor)
9485
}
9586
}
96-
97-
// FIXME: Having to clone `region_constraints` for folding feels bad and
98-
// probably isn't great wrt performance.
99-
//
100-
// Not sure how to fix this, maybe we should also intern `opaque_types` and
101-
// `region_constraints` here or something.
102-
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for PredefinedOpaques<'tcx> {
103-
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
104-
self,
105-
folder: &mut F,
106-
) -> Result<Self, F::Error> {
107-
Ok(FallibleTypeFolder::cx(folder).mk_predefined_opaques_in_body(PredefinedOpaquesData {
108-
opaque_types: self
109-
.opaque_types
110-
.iter()
111-
.map(|opaque| opaque.try_fold_with(folder))
112-
.collect::<Result<_, F::Error>>()?,
113-
}))
114-
}
115-
116-
fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
117-
TypeFolder::cx(folder).mk_predefined_opaques_in_body(PredefinedOpaquesData {
118-
opaque_types: self.opaque_types.iter().map(|opaque| opaque.fold_with(folder)).collect(),
119-
})
120-
}
121-
}
122-
123-
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for PredefinedOpaques<'tcx> {
124-
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
125-
self.opaque_types.visit_with(visitor)
126-
}
127-
}

compiler/rustc_middle/src/ty/context.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ use crate::thir::Thir;
7575
use crate::traits;
7676
use crate::traits::solve::{
7777
self, CanonicalInput, ExternalConstraints, ExternalConstraintsData, PredefinedOpaques,
78-
PredefinedOpaquesData, QueryResult, inspect,
78+
QueryResult, inspect,
7979
};
8080
use crate::ty::predicate::ExistentialPredicateStableCmpExt as _;
8181
use crate::ty::{
@@ -116,7 +116,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
116116

117117
fn mk_predefined_opaques_in_body(
118118
self,
119-
data: PredefinedOpaquesData<Self>,
119+
data: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)],
120120
) -> Self::PredefinedOpaques {
121121
self.mk_predefined_opaques_in_body(data)
122122
}
@@ -941,7 +941,7 @@ pub struct CtxtInterners<'tcx> {
941941
layout: InternedSet<'tcx, LayoutData<FieldIdx, VariantIdx>>,
942942
adt_def: InternedSet<'tcx, AdtDefData>,
943943
external_constraints: InternedSet<'tcx, ExternalConstraintsData<TyCtxt<'tcx>>>,
944-
predefined_opaques_in_body: InternedSet<'tcx, PredefinedOpaquesData<TyCtxt<'tcx>>>,
944+
predefined_opaques_in_body: InternedSet<'tcx, List<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>>,
945945
fields: InternedSet<'tcx, List<FieldIdx>>,
946946
local_def_ids: InternedSet<'tcx, List<LocalDefId>>,
947947
captures: InternedSet<'tcx, List<&'tcx ty::CapturedPlace<'tcx>>>,
@@ -2748,8 +2748,6 @@ direct_interners! {
27482748
adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>,
27492749
external_constraints: pub mk_external_constraints(ExternalConstraintsData<TyCtxt<'tcx>>):
27502750
ExternalConstraints -> ExternalConstraints<'tcx>,
2751-
predefined_opaques_in_body: pub mk_predefined_opaques_in_body(PredefinedOpaquesData<TyCtxt<'tcx>>):
2752-
PredefinedOpaques -> PredefinedOpaques<'tcx>,
27532751
}
27542752

27552753
macro_rules! slice_interners {
@@ -2786,6 +2784,7 @@ slice_interners!(
27862784
offset_of: pub mk_offset_of((VariantIdx, FieldIdx)),
27872785
patterns: pub mk_patterns(Pattern<'tcx>),
27882786
outlives: pub mk_outlives(ty::ArgOutlivesPredicate<'tcx>),
2787+
predefined_opaques_in_body: pub mk_predefined_opaques_in_body((ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)),
27892788
);
27902789

27912790
impl<'tcx> TyCtxt<'tcx> {
@@ -3129,6 +3128,14 @@ impl<'tcx> TyCtxt<'tcx> {
31293128
T::collect_and_apply(iter, |xs| self.mk_poly_existential_predicates(xs))
31303129
}
31313130

3131+
pub fn mk_predefined_opaques_in_body_from_iter<I, T>(self, iter: I) -> T::Output
3132+
where
3133+
I: Iterator<Item = T>,
3134+
T: CollectAndApply<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>), PredefinedOpaques<'tcx>>,
3135+
{
3136+
T::collect_and_apply(iter, |xs| self.mk_predefined_opaques_in_body(xs))
3137+
}
3138+
31323139
pub fn mk_clauses_from_iter<I, T>(self, iter: I) -> T::Output
31333140
where
31343141
I: Iterator<Item = T>,

compiler/rustc_middle/src/ty/structural_impls.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,7 @@ macro_rules! list_fold {
796796

797797
list_fold! {
798798
&'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> : mk_poly_existential_predicates,
799+
&'tcx ty::List<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>: mk_predefined_opaques_in_body,
799800
&'tcx ty::List<PlaceElem<'tcx>> : mk_place_elems,
800801
&'tcx ty::List<ty::Pattern<'tcx>> : mk_patterns,
801802
&'tcx ty::List<ty::ArgOutlivesPredicate<'tcx>> : mk_outlives,

0 commit comments

Comments
 (0)