Skip to content

Commit 5633798

Browse files
committed
Auto merge of rust-lang#113229 - matthiaskrgr:rollup-gunqun4, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - rust-lang#113168 (fix(resolve): skip assertion judgment when NonModule is dummy) - rust-lang#113174 (Better messages for next on a iterator inside for loops) - rust-lang#113182 (Error when RPITITs' hidden types capture more lifetimes than their trait definitions) - rust-lang#113196 (Fix associated items effective visibility calculation for type privacy lints) - rust-lang#113226 (Fix try builds on the msvc builder) - rust-lang#113227 (Update cargo) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 7905eff + f67d59b commit 5633798

File tree

19 files changed

+500
-107
lines changed

19 files changed

+500
-107
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+74-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use std::iter;
2-
31
use either::Either;
2+
use hir::PatField;
43
use rustc_data_structures::captures::Captures;
54
use rustc_data_structures::fx::FxIndexSet;
65
use rustc_errors::{
@@ -28,6 +27,7 @@ use rustc_span::symbol::{kw, sym, Ident};
2827
use rustc_span::{BytePos, Span, Symbol};
2928
use rustc_trait_selection::infer::InferCtxtExt;
3029
use rustc_trait_selection::traits::ObligationCtxt;
30+
use std::iter;
3131

3232
use crate::borrow_set::TwoPhaseActivation;
3333
use crate::borrowck_errors;
@@ -992,6 +992,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
992992
issued_borrow.borrowed_place,
993993
&issued_spans,
994994
);
995+
self.explain_iterator_advancement_in_for_loop_if_applicable(
996+
&mut err,
997+
span,
998+
&issued_spans,
999+
);
9951000
err
9961001
}
9971002

@@ -1279,6 +1284,73 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
12791284
}
12801285
}
12811286

1287+
/// Suggest using `while let` for call `next` on an iterator in a for loop.
1288+
///
1289+
/// For example:
1290+
/// ```ignore (illustrative)
1291+
///
1292+
/// for x in iter {
1293+
/// ...
1294+
/// iter.next()
1295+
/// }
1296+
/// ```
1297+
pub(crate) fn explain_iterator_advancement_in_for_loop_if_applicable(
1298+
&self,
1299+
err: &mut Diagnostic,
1300+
span: Span,
1301+
issued_spans: &UseSpans<'tcx>,
1302+
) {
1303+
let issue_span = issued_spans.args_or_use();
1304+
let tcx = self.infcx.tcx;
1305+
let hir = tcx.hir();
1306+
1307+
let Some(body_id) = hir.get(self.mir_hir_id()).body_id() else { return };
1308+
let typeck_results = tcx.typeck(self.mir_def_id());
1309+
1310+
struct ExprFinder<'hir> {
1311+
issue_span: Span,
1312+
expr_span: Span,
1313+
body_expr: Option<&'hir hir::Expr<'hir>>,
1314+
loop_bind: Option<Symbol>,
1315+
}
1316+
impl<'hir> Visitor<'hir> for ExprFinder<'hir> {
1317+
fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
1318+
if let hir::ExprKind::Loop(hir::Block{ stmts: [stmt, ..], ..}, _, hir::LoopSource::ForLoop, _) = ex.kind &&
1319+
let hir::StmtKind::Expr(hir::Expr{ kind: hir::ExprKind::Match(call, [_, bind, ..], _), ..}) = stmt.kind &&
1320+
let hir::ExprKind::Call(path, _args) = call.kind &&
1321+
let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IteratorNext, _, _, )) = path.kind &&
1322+
let hir::PatKind::Struct(path, [field, ..], _) = bind.pat.kind &&
1323+
let hir::QPath::LangItem(LangItem::OptionSome, _, _) = path &&
1324+
let PatField { pat: hir::Pat{ kind: hir::PatKind::Binding(_, _, ident, ..), .. }, ..} = field &&
1325+
self.issue_span.source_equal(call.span) {
1326+
self.loop_bind = Some(ident.name);
1327+
}
1328+
1329+
if let hir::ExprKind::MethodCall(body_call, _recv, ..) = ex.kind &&
1330+
body_call.ident.name == sym::next && ex.span.source_equal(self.expr_span) {
1331+
self.body_expr = Some(ex);
1332+
}
1333+
1334+
hir::intravisit::walk_expr(self, ex);
1335+
}
1336+
}
1337+
let mut finder =
1338+
ExprFinder { expr_span: span, issue_span, loop_bind: None, body_expr: None };
1339+
finder.visit_expr(hir.body(body_id).value);
1340+
1341+
if let Some(loop_bind) = finder.loop_bind &&
1342+
let Some(body_expr) = finder.body_expr &&
1343+
let Some(def_id) = typeck_results.type_dependent_def_id(body_expr.hir_id) &&
1344+
let Some(trait_did) = tcx.trait_of_item(def_id) &&
1345+
tcx.is_diagnostic_item(sym::Iterator, trait_did) {
1346+
err.note(format!(
1347+
"a for loop advances the iterator for you, the result is stored in `{}`.",
1348+
loop_bind
1349+
));
1350+
err.help("if you want to call `next` on a iterator within the loop, consider using `while let`.");
1351+
}
1352+
}
1353+
12821354
/// Suggest using closure argument instead of capture.
12831355
///
12841356
/// For example:

compiler/rustc_borrowck/src/diagnostics/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1146,6 +1146,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
11461146
// Avoid pointing to the same function in multiple different
11471147
// error messages.
11481148
if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) {
1149+
self.explain_iterator_advancement_in_for_loop_if_applicable(
1150+
err,
1151+
span,
1152+
&move_spans,
1153+
);
1154+
11491155
let func = tcx.def_path_str(method_did);
11501156
err.subdiagnostic(CaptureReasonNote::FuncTakeSelf {
11511157
func,

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

+116-32
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use rustc_middle::ty::{
1919
self, InternalSubsts, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
2020
};
2121
use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
22-
use rustc_span::Span;
22+
use rustc_span::{Span, DUMMY_SP};
2323
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
2424
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
2525
use rustc_trait_selection::traits::{
@@ -651,11 +651,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
651651
let impl_sig = ocx.normalize(
652652
&norm_cause,
653653
param_env,
654-
infcx.instantiate_binder_with_fresh_vars(
655-
return_span,
656-
infer::HigherRankedType,
657-
tcx.fn_sig(impl_m.def_id).subst_identity(),
658-
),
654+
tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(impl_m.def_id).subst_identity()),
659655
);
660656
impl_sig.error_reported()?;
661657
let impl_return_ty = impl_sig.output();
@@ -665,9 +661,10 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
665661
// them with inference variables.
666662
// We will use these inference variables to collect the hidden types of RPITITs.
667663
let mut collector = ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_def_id);
668-
let unnormalized_trait_sig = tcx
669-
.liberate_late_bound_regions(
670-
impl_m.def_id,
664+
let unnormalized_trait_sig = infcx
665+
.instantiate_binder_with_fresh_vars(
666+
return_span,
667+
infer::HigherRankedType,
671668
tcx.fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs),
672669
)
673670
.fold_with(&mut collector);
@@ -760,15 +757,17 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
760757

761758
let mut collected_tys = FxHashMap::default();
762759
for (def_id, (ty, substs)) in collected_types {
763-
match infcx.fully_resolve(ty) {
764-
Ok(ty) => {
760+
match infcx.fully_resolve((ty, substs)) {
761+
Ok((ty, substs)) => {
765762
// `ty` contains free regions that we created earlier while liberating the
766763
// trait fn signature. However, projection normalization expects `ty` to
767764
// contains `def_id`'s early-bound regions.
768765
let id_substs = InternalSubsts::identity_for_item(tcx, def_id);
769766
debug!(?id_substs, ?substs);
770-
let map: FxHashMap<ty::GenericArg<'tcx>, ty::GenericArg<'tcx>> =
771-
std::iter::zip(substs, id_substs).collect();
767+
let map: FxHashMap<_, _> = std::iter::zip(substs, id_substs)
768+
.skip(tcx.generics_of(trait_m.def_id).count())
769+
.filter_map(|(a, b)| Some((a.as_region()?, b.as_region()?)))
770+
.collect();
772771
debug!(?map);
773772

774773
// NOTE(compiler-errors): RPITITs, like all other RPITs, have early-bound
@@ -793,25 +792,19 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
793792
// same generics.
794793
let num_trait_substs = trait_to_impl_substs.len();
795794
let num_impl_substs = tcx.generics_of(impl_m.container_id(tcx)).params.len();
796-
let ty = tcx.fold_regions(ty, |region, _| {
797-
match region.kind() {
798-
// Remap all free regions, which correspond to late-bound regions in the function.
799-
ty::ReFree(_) => {}
800-
// Remap early-bound regions as long as they don't come from the `impl` itself.
801-
ty::ReEarlyBound(ebr) if tcx.parent(ebr.def_id) != impl_m.container_id(tcx) => {}
802-
_ => return region,
803-
}
804-
let Some(ty::ReEarlyBound(e)) = map.get(&region.into()).map(|r| r.expect_region().kind())
805-
else {
806-
return ty::Region::new_error_with_message(tcx, return_span, "expected ReFree to map to ReEarlyBound")
807-
};
808-
ty::Region::new_early_bound(tcx, ty::EarlyBoundRegion {
809-
def_id: e.def_id,
810-
name: e.name,
811-
index: (e.index as usize - num_trait_substs + num_impl_substs) as u32,
812-
})
813-
});
814-
debug!(%ty);
795+
let ty = match ty.try_fold_with(&mut RemapHiddenTyRegions {
796+
tcx,
797+
map,
798+
num_trait_substs,
799+
num_impl_substs,
800+
def_id,
801+
impl_def_id: impl_m.container_id(tcx),
802+
ty,
803+
return_span,
804+
}) {
805+
Ok(ty) => ty,
806+
Err(guar) => tcx.ty_error(guar),
807+
};
815808
collected_tys.insert(def_id, ty::EarlyBinder::bind(ty));
816809
}
817810
Err(err) => {
@@ -895,6 +888,97 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
895888
}
896889
}
897890

891+
struct RemapHiddenTyRegions<'tcx> {
892+
tcx: TyCtxt<'tcx>,
893+
map: FxHashMap<ty::Region<'tcx>, ty::Region<'tcx>>,
894+
num_trait_substs: usize,
895+
num_impl_substs: usize,
896+
def_id: DefId,
897+
impl_def_id: DefId,
898+
ty: Ty<'tcx>,
899+
return_span: Span,
900+
}
901+
902+
impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
903+
type Error = ErrorGuaranteed;
904+
905+
fn interner(&self) -> TyCtxt<'tcx> {
906+
self.tcx
907+
}
908+
909+
fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
910+
if let ty::Alias(ty::Opaque, ty::AliasTy { substs, def_id, .. }) = *t.kind() {
911+
let mut mapped_substs = Vec::with_capacity(substs.len());
912+
for (arg, v) in std::iter::zip(substs, self.tcx.variances_of(def_id)) {
913+
mapped_substs.push(match (arg.unpack(), v) {
914+
// Skip uncaptured opaque substs
915+
(ty::GenericArgKind::Lifetime(_), ty::Bivariant) => arg,
916+
_ => arg.try_fold_with(self)?,
917+
});
918+
}
919+
Ok(self.tcx.mk_opaque(def_id, self.tcx.mk_substs(&mapped_substs)))
920+
} else {
921+
t.try_super_fold_with(self)
922+
}
923+
}
924+
925+
fn try_fold_region(
926+
&mut self,
927+
region: ty::Region<'tcx>,
928+
) -> Result<ty::Region<'tcx>, Self::Error> {
929+
match region.kind() {
930+
// Remap all free regions, which correspond to late-bound regions in the function.
931+
ty::ReFree(_) => {}
932+
// Remap early-bound regions as long as they don't come from the `impl` itself,
933+
// in which case we don't really need to renumber them.
934+
ty::ReEarlyBound(ebr) if self.tcx.parent(ebr.def_id) != self.impl_def_id => {}
935+
_ => return Ok(region),
936+
}
937+
938+
let e = if let Some(region) = self.map.get(&region) {
939+
if let ty::ReEarlyBound(e) = region.kind() { e } else { bug!() }
940+
} else {
941+
let guar = match region.kind() {
942+
ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, .. })
943+
| ty::ReFree(ty::FreeRegion {
944+
bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
945+
..
946+
}) => {
947+
let return_span = if let ty::Alias(ty::Opaque, opaque_ty) = self.ty.kind() {
948+
self.tcx.def_span(opaque_ty.def_id)
949+
} else {
950+
self.return_span
951+
};
952+
self.tcx
953+
.sess
954+
.struct_span_err(
955+
return_span,
956+
"return type captures more lifetimes than trait definition",
957+
)
958+
.span_label(self.tcx.def_span(def_id), "this lifetime was captured")
959+
.span_note(
960+
self.tcx.def_span(self.def_id),
961+
"hidden type must only reference lifetimes captured by this impl trait",
962+
)
963+
.note(format!("hidden type inferred to be `{}`", self.ty))
964+
.emit()
965+
}
966+
_ => self.tcx.sess.delay_span_bug(DUMMY_SP, "should've been able to remap region"),
967+
};
968+
return Err(guar);
969+
};
970+
971+
Ok(ty::Region::new_early_bound(
972+
self.tcx,
973+
ty::EarlyBoundRegion {
974+
def_id: e.def_id,
975+
name: e.name,
976+
index: (e.index as usize - self.num_trait_substs + self.num_impl_substs) as u32,
977+
},
978+
))
979+
}
980+
}
981+
898982
fn report_trait_method_mismatch<'tcx>(
899983
infcx: &InferCtxt<'tcx>,
900984
mut cause: ObligationCause<'tcx>,

compiler/rustc_privacy/src/lib.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -2135,16 +2135,18 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx, '_> {
21352135
// lints shouldn't be emmited even if `from` effective visibility
21362136
// is larger than `Priv` nominal visibility and if `Priv` can leak
21372137
// in some scenarios due to type inference.
2138-
let impl_ev = Some(EffectiveVisibility::of_impl::<false>(
2138+
let impl_ev = EffectiveVisibility::of_impl::<false>(
21392139
item.owner_id.def_id,
21402140
tcx,
21412141
self.effective_visibilities,
2142-
));
2142+
);
21432143

21442144
// check that private components do not appear in the generics or predicates of inherent impls
21452145
// this check is intentionally NOT performed for impls of traits, per #90586
21462146
if impl_.of_trait.is_none() {
2147-
self.check(item.owner_id.def_id, impl_vis, impl_ev).generics().predicates();
2147+
self.check(item.owner_id.def_id, impl_vis, Some(impl_ev))
2148+
.generics()
2149+
.predicates();
21482150
}
21492151
for impl_item_ref in impl_.items {
21502152
let impl_item_vis = if impl_.of_trait.is_none() {
@@ -2159,8 +2161,9 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx, '_> {
21592161

21602162
let impl_item_ev = if impl_.of_trait.is_none() {
21612163
self.get(impl_item_ref.id.owner_id.def_id)
2164+
.map(|ev| ev.min(impl_ev, self.tcx))
21622165
} else {
2163-
impl_ev
2166+
Some(impl_ev)
21642167
};
21652168

21662169
self.check_assoc_item(

compiler/rustc_resolve/src/ident.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
370370
/// expansion and import resolution (perhaps they can be merged in the future).
371371
/// The function is used for resolving initial segments of macro paths (e.g., `foo` in
372372
/// `foo::bar!();` or `foo!();`) and also for import paths on 2018 edition.
373-
#[instrument(level = "debug", skip(self, scope_set))]
373+
#[instrument(level = "debug", skip(self))]
374374
pub(crate) fn early_resolve_ident_in_lexical_scope(
375375
&mut self,
376376
orig_ident: Ident,

compiler/rustc_resolve/src/imports.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -894,8 +894,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
894894
}
895895
return None;
896896
}
897-
PathResult::NonModule(_) => {
898-
if no_ambiguity {
897+
PathResult::NonModule(partial_res) => {
898+
if no_ambiguity && partial_res.full_res() != Some(Res::Err) {
899+
// Check if there are no ambiguities and the result is not dummy.
899900
assert!(import.imported_module.get().is_none());
900901
}
901902
// The error was already reported earlier.

compiler/rustc_resolve/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ enum Scope<'a> {
128128
/// with different restrictions when looking up the resolution.
129129
/// This enum is currently used only for early resolution (imports and macros),
130130
/// but not for late resolution yet.
131-
#[derive(Clone, Copy)]
131+
#[derive(Clone, Copy, Debug)]
132132
enum ScopeSet<'a> {
133133
/// All scopes with the given namespace.
134134
All(Namespace),

0 commit comments

Comments
 (0)