Skip to content

Commit cdf9d15

Browse files
committed
Auto merge of #151681 - Zalathar:rollup-2s4yN8G, r=Zalathar
Rollup of 3 pull requests Successful merges: - #151676 (Do not return incorrectly constrained opaques in `method_autoderef_steps`) - #151626 (Remove `Deref<Target = TyCtxt>` from `QueryCtxt`) - #151661 (Suggest changing `iter`/`into_iter` when the other was meant)
2 parents db6bc0f + b292003 commit cdf9d15

11 files changed

Lines changed: 247 additions & 34 deletions

File tree

compiler/rustc_hir_typeck/src/method/probe.rs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -415,10 +415,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
415415
infcx.instantiate_canonical(span, &query_input.canonical);
416416
let query::MethodAutoderefSteps { predefined_opaques_in_body: _, self_ty } = value;
417417
debug!(?self_ty, ?query_input, "probe_op: Mode::Path");
418+
let prev_opaque_entries = self.inner.borrow_mut().opaque_types().num_entries();
418419
MethodAutoderefStepsResult {
419420
steps: infcx.tcx.arena.alloc_from_iter([CandidateStep {
420-
self_ty: self
421-
.make_query_response_ignoring_pending_obligations(var_values, self_ty),
421+
self_ty: self.make_query_response_ignoring_pending_obligations(
422+
var_values,
423+
self_ty,
424+
prev_opaque_entries,
425+
),
422426
self_ty_is_opaque: false,
423427
autoderefs: 0,
424428
from_unsafe_deref: false,
@@ -607,6 +611,7 @@ pub(crate) fn method_autoderef_steps<'tcx>(
607611
debug!(?key, ?ty, ?prev, "ignore duplicate in `opaque_types_storage`");
608612
}
609613
}
614+
let prev_opaque_entries = infcx.inner.borrow_mut().opaque_types().num_entries();
610615

611616
// We accept not-yet-defined opaque types in the autoderef
612617
// chain to support recursive calls. We do error if the final
@@ -650,8 +655,11 @@ pub(crate) fn method_autoderef_steps<'tcx>(
650655
.zip(reachable_via_deref)
651656
.map(|((ty, d), reachable_via_deref)| {
652657
let step = CandidateStep {
653-
self_ty: infcx
654-
.make_query_response_ignoring_pending_obligations(inference_vars, ty),
658+
self_ty: infcx.make_query_response_ignoring_pending_obligations(
659+
inference_vars,
660+
ty,
661+
prev_opaque_entries,
662+
),
655663
self_ty_is_opaque: self_ty_is_opaque(ty),
656664
autoderefs: d,
657665
from_unsafe_deref: reached_raw_pointer,
@@ -671,8 +679,11 @@ pub(crate) fn method_autoderef_steps<'tcx>(
671679
.by_ref()
672680
.map(|(ty, d)| {
673681
let step = CandidateStep {
674-
self_ty: infcx
675-
.make_query_response_ignoring_pending_obligations(inference_vars, ty),
682+
self_ty: infcx.make_query_response_ignoring_pending_obligations(
683+
inference_vars,
684+
ty,
685+
prev_opaque_entries,
686+
),
676687
self_ty_is_opaque: self_ty_is_opaque(ty),
677688
autoderefs: d,
678689
from_unsafe_deref: reached_raw_pointer,
@@ -692,18 +703,27 @@ pub(crate) fn method_autoderef_steps<'tcx>(
692703
let opt_bad_ty = match final_ty.kind() {
693704
ty::Infer(ty::TyVar(_)) if !self_ty_is_opaque(final_ty) => Some(MethodAutoderefBadTy {
694705
reached_raw_pointer,
695-
ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, final_ty),
706+
ty: infcx.make_query_response_ignoring_pending_obligations(
707+
inference_vars,
708+
final_ty,
709+
prev_opaque_entries,
710+
),
696711
}),
697712
ty::Error(_) => Some(MethodAutoderefBadTy {
698713
reached_raw_pointer,
699-
ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, final_ty),
714+
ty: infcx.make_query_response_ignoring_pending_obligations(
715+
inference_vars,
716+
final_ty,
717+
prev_opaque_entries,
718+
),
700719
}),
701720
ty::Array(elem_ty, _) => {
702721
let autoderefs = steps.iter().filter(|s| s.reachable_via_deref).count() - 1;
703722
steps.push(CandidateStep {
704723
self_ty: infcx.make_query_response_ignoring_pending_obligations(
705724
inference_vars,
706725
Ty::new_slice(infcx.tcx, *elem_ty),
726+
prev_opaque_entries,
707727
),
708728
self_ty_is_opaque: false,
709729
autoderefs,

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ use crate::infer::canonical::{
2424
};
2525
use crate::infer::region_constraints::RegionConstraintData;
2626
use crate::infer::{
27-
DefineOpaqueTypes, InferCtxt, InferOk, InferResult, SubregionOrigin, TypeOutlivesConstraint,
27+
DefineOpaqueTypes, InferCtxt, InferOk, InferResult, OpaqueTypeStorageEntries, SubregionOrigin,
28+
TypeOutlivesConstraint,
2829
};
2930
use crate::traits::query::NoSolution;
3031
use crate::traits::{ObligationCause, PredicateObligations, ScrubbedTraitError, TraitEngine};
@@ -81,6 +82,7 @@ impl<'tcx> InferCtxt<'tcx> {
8182
&self,
8283
inference_vars: CanonicalVarValues<'tcx>,
8384
answer: T,
85+
prev_entries: OpaqueTypeStorageEntries,
8486
) -> Canonical<'tcx, QueryResponse<'tcx, T>>
8587
where
8688
T: Debug + TypeFoldable<TyCtxt<'tcx>>,
@@ -96,7 +98,7 @@ impl<'tcx> InferCtxt<'tcx> {
9698
self.inner
9799
.borrow_mut()
98100
.opaque_type_storage
99-
.iter_opaque_types()
101+
.opaque_types_added_since(prev_entries)
100102
.map(|(k, v)| (k, v.ty))
101103
.collect()
102104
} else {

compiler/rustc_query_impl/src/plumbing.rs

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ use rustc_span::def_id::LOCAL_CRATE;
3535

3636
use crate::QueryConfigRestored;
3737

38+
/// Implements [`QueryContext`] for use by [`rustc_query_system`], since that
39+
/// crate does not have direct access to [`TyCtxt`].
3840
#[derive(Copy, Clone)]
3941
pub struct QueryCtxt<'tcx> {
4042
pub tcx: TyCtxt<'tcx>,
@@ -47,15 +49,6 @@ impl<'tcx> QueryCtxt<'tcx> {
4749
}
4850
}
4951

50-
impl<'tcx> std::ops::Deref for QueryCtxt<'tcx> {
51-
type Target = TyCtxt<'tcx>;
52-
53-
#[inline]
54-
fn deref(&self) -> &Self::Target {
55-
&self.tcx
56-
}
57-
}
58-
5952
impl<'tcx> HasDepContext for QueryCtxt<'tcx> {
6053
type Deps = rustc_middle::dep_graph::DepsType;
6154
type DepContext = TyCtxt<'tcx>;
@@ -69,14 +62,16 @@ impl<'tcx> HasDepContext for QueryCtxt<'tcx> {
6962
impl QueryContext for QueryCtxt<'_> {
7063
#[inline]
7164
fn jobserver_proxy(&self) -> &Proxy {
72-
&*self.jobserver_proxy
65+
&self.tcx.jobserver_proxy
7366
}
7467

7568
#[inline]
7669
fn next_job_id(self) -> QueryJobId {
7770
QueryJobId(
78-
NonZero::new(self.query_system.jobs.fetch_add(1, std::sync::atomic::Ordering::Relaxed))
79-
.unwrap(),
71+
NonZero::new(
72+
self.tcx.query_system.jobs.fetch_add(1, std::sync::atomic::Ordering::Relaxed),
73+
)
74+
.unwrap(),
8075
)
8176
}
8277

@@ -113,7 +108,8 @@ impl QueryContext for QueryCtxt<'_> {
113108
self,
114109
prev_dep_node_index: SerializedDepNodeIndex,
115110
) -> Option<QuerySideEffect> {
116-
self.query_system
111+
self.tcx
112+
.query_system
117113
.on_disk_cache
118114
.as_ref()
119115
.and_then(|c| c.load_side_effect(self.tcx, prev_dep_node_index))
@@ -122,7 +118,7 @@ impl QueryContext for QueryCtxt<'_> {
122118
#[inline(never)]
123119
#[cold]
124120
fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect) {
125-
if let Some(c) = self.query_system.on_disk_cache.as_ref() {
121+
if let Some(c) = self.tcx.query_system.on_disk_cache.as_ref() {
126122
c.store_side_effect(dep_node_index, side_effect)
127123
}
128124
}
@@ -140,7 +136,9 @@ impl QueryContext for QueryCtxt<'_> {
140136
// as `self`, so we use `with_related_context` to relate the 'tcx lifetimes
141137
// when accessing the `ImplicitCtxt`.
142138
tls::with_related_context(self.tcx, move |current_icx| {
143-
if depth_limit && !self.recursion_limit().value_within_limit(current_icx.query_depth) {
139+
if depth_limit
140+
&& !self.tcx.recursion_limit().value_within_limit(current_icx.query_depth)
141+
{
144142
self.depth_limit_error(token);
145143
}
146144

@@ -161,16 +159,16 @@ impl QueryContext for QueryCtxt<'_> {
161159
let query_map = self.collect_active_jobs(true).expect("failed to collect active queries");
162160
let (info, depth) = job.find_dep_kind_root(query_map);
163161

164-
let suggested_limit = match self.recursion_limit() {
162+
let suggested_limit = match self.tcx.recursion_limit() {
165163
Limit(0) => Limit(2),
166164
limit => limit * 2,
167165
};
168166

169-
self.sess.dcx().emit_fatal(QueryOverflow {
167+
self.tcx.sess.dcx().emit_fatal(QueryOverflow {
170168
span: info.job.span,
171169
note: QueryOverflowNote { desc: info.query.description, depth },
172170
suggested_limit,
173-
crate_name: self.crate_name(LOCAL_CRATE),
171+
crate_name: self.tcx.crate_name(LOCAL_CRATE),
174172
});
175173
}
176174
}
@@ -367,7 +365,7 @@ pub(crate) fn encode_query_results<'a, 'tcx, Q>(
367365
Q: super::QueryConfigRestored<'tcx>,
368366
Q::RestoredValue: Encodable<CacheEncoder<'a, 'tcx>>,
369367
{
370-
let _timer = qcx.profiler().generic_activity_with_arg("encode_query_results_for", query.name());
368+
let _timer = qcx.tcx.prof.generic_activity_with_arg("encode_query_results_for", query.name());
371369

372370
assert!(query.query_state(qcx).all_inactive());
373371
let cache = query.query_cache(qcx);
@@ -389,8 +387,7 @@ pub(crate) fn query_key_hash_verify<'tcx>(
389387
query: impl QueryConfig<QueryCtxt<'tcx>>,
390388
qcx: QueryCtxt<'tcx>,
391389
) {
392-
let _timer =
393-
qcx.profiler().generic_activity_with_arg("query_key_hash_verify_for", query.name());
390+
let _timer = qcx.tcx.prof.generic_activity_with_arg("query_key_hash_verify_for", query.name());
394391

395392
let mut map = UnordMap::default();
396393

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ symbols! {
270270
Into,
271271
IntoFuture,
272272
IntoIterator,
273+
IntoIteratorItem,
273274
IoBufRead,
274275
IoLines,
275276
IoRead,

compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4390,6 +4390,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
43904390
param_env: ty::ParamEnv<'tcx>,
43914391
path_segment: &hir::PathSegment<'_>,
43924392
args: &[hir::Expr<'_>],
4393+
prev_ty: Ty<'_>,
43934394
err: &mut Diag<'_, G>,
43944395
) {
43954396
let tcx = self.tcx;
@@ -4403,6 +4404,47 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
44034404
let TypeError::Sorts(expected_found) = diff else {
44044405
continue;
44054406
};
4407+
if tcx.is_diagnostic_item(sym::IntoIteratorItem, *def_id)
4408+
&& path_segment.ident.name == sym::iter
4409+
&& self.can_eq(
4410+
param_env,
4411+
Ty::new_ref(
4412+
tcx,
4413+
tcx.lifetimes.re_erased,
4414+
expected_found.found,
4415+
ty::Mutability::Not,
4416+
),
4417+
*ty,
4418+
)
4419+
&& let [] = args
4420+
{
4421+
// Used `.iter()` when `.into_iter()` was likely meant.
4422+
err.span_suggestion_verbose(
4423+
path_segment.ident.span,
4424+
format!("consider consuming the `{prev_ty}` to construct the `Iterator`"),
4425+
"into_iter".to_string(),
4426+
Applicability::MachineApplicable,
4427+
);
4428+
}
4429+
if tcx.is_diagnostic_item(sym::IntoIteratorItem, *def_id)
4430+
&& path_segment.ident.name == sym::into_iter
4431+
&& self.can_eq(
4432+
param_env,
4433+
expected_found.found,
4434+
Ty::new_ref(tcx, tcx.lifetimes.re_erased, *ty, ty::Mutability::Not),
4435+
)
4436+
&& let [] = args
4437+
{
4438+
// Used `.into_iter()` when `.iter()` was likely meant.
4439+
err.span_suggestion_verbose(
4440+
path_segment.ident.span,
4441+
format!(
4442+
"consider not consuming the `{prev_ty}` to construct the `Iterator`"
4443+
),
4444+
"iter".to_string(),
4445+
Applicability::MachineApplicable,
4446+
);
4447+
}
44064448
if tcx.is_diagnostic_item(sym::IteratorItem, *def_id)
44074449
&& path_segment.ident.name == sym::map
44084450
&& self.can_eq(param_env, expected_found.found, *ty)
@@ -4515,19 +4557,20 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
45154557
expr = rcvr_expr;
45164558
let assocs_in_this_method =
45174559
self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env);
4560+
prev_ty = self.resolve_vars_if_possible(
4561+
typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)),
4562+
);
45184563
self.look_for_iterator_item_mistakes(
45194564
&assocs_in_this_method,
45204565
typeck_results,
45214566
&type_diffs,
45224567
param_env,
45234568
path_segment,
45244569
args,
4570+
prev_ty,
45254571
err,
45264572
);
45274573
assocs.push(assocs_in_this_method);
4528-
prev_ty = self.resolve_vars_if_possible(
4529-
typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)),
4530-
);
45314574

45324575
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
45334576
&& let hir::Path { res: Res::Local(hir_id), .. } = path

library/core/src/iter/traits/collect.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ pub trait FromIterator<A>: Sized {
281281
#[stable(feature = "rust1", since = "1.0.0")]
282282
pub trait IntoIterator {
283283
/// The type of the elements being iterated over.
284+
#[rustc_diagnostic_item = "IntoIteratorItem"]
284285
#[stable(feature = "rust1", since = "1.0.0")]
285286
type Item;
286287

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//@ run-rustfix
2+
//@ edition:2021
3+
// Suggest using the right `IntoIterator` method. #68095
4+
fn main() {
5+
let _a = [0, 1, 2].iter().chain([3, 4, 5].iter()); //~ ERROR E0271
6+
let _b = [0, 1, 2].into_iter().chain([3, 4, 5].into_iter()); //~ ERROR E0271
7+
// These don't have appropriate suggestions yet.
8+
// let c = [0, 1, 2].iter().chain([3, 4, 5]);
9+
// let d = [0, 1, 2].iter().chain(vec![3, 4, 5]);
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//@ run-rustfix
2+
//@ edition:2021
3+
// Suggest using the right `IntoIterator` method. #68095
4+
fn main() {
5+
let _a = [0, 1, 2].iter().chain([3, 4, 5].into_iter()); //~ ERROR E0271
6+
let _b = [0, 1, 2].into_iter().chain([3, 4, 5].iter()); //~ ERROR E0271
7+
// These don't have appropriate suggestions yet.
8+
// let c = [0, 1, 2].iter().chain([3, 4, 5]);
9+
// let d = [0, 1, 2].iter().chain(vec![3, 4, 5]);
10+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
error[E0271]: type mismatch resolving `<IntoIter<{integer}, 3> as IntoIterator>::Item == &{integer}`
2+
--> $DIR/into_iter-when-iter-was-intended.rs:5:37
3+
|
4+
LL | let _a = [0, 1, 2].iter().chain([3, 4, 5].into_iter());
5+
| ----- ^^^^^^^^^^^^^^^^^^^^^ expected `&{integer}`, found integer
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
note: the method call chain might not have had the expected associated types
10+
--> $DIR/into_iter-when-iter-was-intended.rs:5:47
11+
|
12+
LL | let _a = [0, 1, 2].iter().chain([3, 4, 5].into_iter());
13+
| --------- ^^^^^^^^^^^ `IntoIterator::Item` is `{integer}` here
14+
| |
15+
| this expression has type `[{integer}; 3]`
16+
note: required by a bound in `std::iter::Iterator::chain`
17+
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
18+
help: consider not consuming the `[{integer}; 3]` to construct the `Iterator`
19+
|
20+
LL - let _a = [0, 1, 2].iter().chain([3, 4, 5].into_iter());
21+
LL + let _a = [0, 1, 2].iter().chain([3, 4, 5].iter());
22+
|
23+
24+
error[E0271]: type mismatch resolving `<Iter<'_, {integer}> as IntoIterator>::Item == {integer}`
25+
--> $DIR/into_iter-when-iter-was-intended.rs:6:42
26+
|
27+
LL | let _b = [0, 1, 2].into_iter().chain([3, 4, 5].iter());
28+
| ----- ^^^^^^^^^^^^^^^^ expected integer, found `&{integer}`
29+
| |
30+
| required by a bound introduced by this call
31+
|
32+
note: the method call chain might not have had the expected associated types
33+
--> $DIR/into_iter-when-iter-was-intended.rs:6:52
34+
|
35+
LL | let _b = [0, 1, 2].into_iter().chain([3, 4, 5].iter());
36+
| --------- ^^^^^^ `IntoIterator::Item` is `&{integer}` here
37+
| |
38+
| this expression has type `[{integer}; 3]`
39+
note: required by a bound in `std::iter::Iterator::chain`
40+
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
41+
help: consider consuming the `&[{integer}]` to construct the `Iterator`
42+
|
43+
LL | let _b = [0, 1, 2].into_iter().chain([3, 4, 5].into_iter());
44+
| +++++
45+
46+
error: aborting due to 2 previous errors
47+
48+
For more information about this error, try `rustc --explain E0271`.

0 commit comments

Comments
 (0)