Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 5922ed2

Browse files
committedMar 21, 2025
add TypingMode::Borrowck
1 parent f88824b commit 5922ed2

File tree

38 files changed

+665
-550
lines changed

38 files changed

+665
-550
lines changed
 

‎compiler/rustc_borrowck/messages.ftl

-7
Original file line numberDiff line numberDiff line change
@@ -162,13 +162,6 @@ borrowck_opaque_type_lifetime_mismatch =
162162
.prev_lifetime_label = lifetime `{$prev}` previously used here
163163
.note = if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
164164
165-
borrowck_opaque_type_non_generic_param =
166-
expected generic {$kind} parameter, found `{$ty}`
167-
.label = {STREQ($ty, "'static") ->
168-
[true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
169-
*[other] this generic parameter must be used with a generic {$kind} parameter
170-
}
171-
172165
borrowck_partial_var_move_by_use_in_closure =
173166
variable {$is_partial ->
174167
[true] partially moved

‎compiler/rustc_borrowck/src/consumers.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! This file provides API for compiler consumers.
22
33
use rustc_hir::def_id::LocalDefId;
4-
use rustc_index::{IndexSlice, IndexVec};
4+
use rustc_index::IndexVec;
55
use rustc_middle::mir::{Body, Promoted};
66
use rustc_middle::ty::TyCtxt;
77

@@ -100,8 +100,5 @@ pub fn get_body_with_borrowck_facts(
100100
def: LocalDefId,
101101
options: ConsumerOptions,
102102
) -> BodyWithBorrowckFacts<'_> {
103-
let (input_body, promoted) = tcx.mir_promoted(def);
104-
let input_body: &Body<'_> = &input_body.borrow();
105-
let promoted: &IndexSlice<_, _> = &promoted.borrow();
106-
*super::do_mir_borrowck(tcx, input_body, promoted, Some(options)).1.unwrap()
103+
*super::do_mir_borrowck(tcx, def, Some(options)).1.unwrap()
107104
}

‎compiler/rustc_borrowck/src/lib.rs

+9-39
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use rustc_infer::infer::{
3535
};
3636
use rustc_middle::mir::*;
3737
use rustc_middle::query::Providers;
38-
use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode, fold_regions};
38+
use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode};
3939
use rustc_middle::{bug, span_bug};
4040
use rustc_mir_dataflow::impls::{
4141
EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces,
@@ -103,11 +103,8 @@ pub fn provide(providers: &mut Providers) {
103103
}
104104

105105
fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
106-
let (input_body, promoted) = tcx.mir_promoted(def);
107-
debug!("run query mir_borrowck: {}", tcx.def_path_str(def));
108-
106+
let (input_body, _0) = tcx.mir_promoted(def);
109107
let input_body: &Body<'_> = &input_body.borrow();
110-
111108
if input_body.should_skip() || input_body.tainted_by_errors.is_some() {
112109
debug!("Skipping borrowck because of injected body or tainted body");
113110
// Let's make up a borrowck result! Fun times!
@@ -120,7 +117,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
120117
return tcx.arena.alloc(result);
121118
}
122119

123-
let borrowck_result = do_mir_borrowck(tcx, input_body, &*promoted.borrow(), None).0;
120+
let borrowck_result = do_mir_borrowck(tcx, def, None).0;
124121
debug!("mir_borrowck done");
125122

126123
tcx.arena.alloc(borrowck_result)
@@ -131,15 +128,16 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
131128
/// Use `consumer_options: None` for the default behavior of returning
132129
/// [`BorrowCheckResult`] only. Otherwise, return [`BodyWithBorrowckFacts`] according
133130
/// to the given [`ConsumerOptions`].
134-
#[instrument(skip(tcx, input_body, input_promoted), fields(id=?input_body.source.def_id()), level = "debug")]
131+
#[instrument(skip(tcx), level = "debug")]
135132
fn do_mir_borrowck<'tcx>(
136133
tcx: TyCtxt<'tcx>,
137-
input_body: &Body<'tcx>,
138-
input_promoted: &IndexSlice<Promoted, Body<'tcx>>,
134+
def: LocalDefId,
139135
consumer_options: Option<ConsumerOptions>,
140136
) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
141-
let def = input_body.source.def_id().expect_local();
142137
let infcx = BorrowckInferCtxt::new(tcx, def);
138+
let (input_body, promoted) = tcx.mir_promoted(def);
139+
let input_body: &Body<'_> = &input_body.borrow();
140+
let input_promoted: &IndexSlice<_, _> = &promoted.borrow();
143141
if let Some(e) = input_body.tainted_by_errors {
144142
infcx.set_tainted_by_errors(e);
145143
}
@@ -173,12 +171,6 @@ fn do_mir_borrowck<'tcx>(
173171
let free_regions = nll::replace_regions_in_mir(&infcx, &mut body_owned, &mut promoted);
174172
let body = &body_owned; // no further changes
175173

176-
// FIXME(-Znext-solver): A bit dubious that we're only registering
177-
// predefined opaques in the typeck root.
178-
if infcx.next_trait_solver() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
179-
infcx.register_predefined_opaques_for_next_solver(def);
180-
}
181-
182174
let location_table = PoloniusLocationTable::new(body);
183175

184176
let move_data = MoveData::gather_moves(body, tcx, |_| true);
@@ -433,7 +425,7 @@ pub(crate) struct BorrowckInferCtxt<'tcx> {
433425

434426
impl<'tcx> BorrowckInferCtxt<'tcx> {
435427
pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
436-
let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, def_id));
428+
let infcx = tcx.infer_ctxt().build(TypingMode::borrowck(tcx, def_id));
437429
let param_env = tcx.param_env(def_id);
438430
BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()), param_env }
439431
}
@@ -480,28 +472,6 @@ impl<'tcx> BorrowckInferCtxt<'tcx> {
480472

481473
next_region
482474
}
483-
484-
/// With the new solver we prepopulate the opaque type storage during
485-
/// MIR borrowck with the hidden types from HIR typeck. This is necessary
486-
/// to avoid ambiguities as earlier goals can rely on the hidden type
487-
/// of an opaque which is only constrained by a later goal.
488-
fn register_predefined_opaques_for_next_solver(&self, def_id: LocalDefId) {
489-
let tcx = self.tcx;
490-
// OK to use the identity arguments for each opaque type key, since
491-
// we remap opaques from HIR typeck back to their definition params.
492-
for data in tcx.typeck(def_id).concrete_opaque_types.iter().map(|(k, v)| (*k, *v)) {
493-
// HIR typeck did not infer the regions of the opaque, so we instantiate
494-
// them with fresh inference variables.
495-
let (key, hidden_ty) = fold_regions(tcx, data, |_, _| {
496-
self.next_nll_region_var_in_universe(
497-
NllRegionVariableOrigin::Existential { from_forall: false },
498-
ty::UniverseIndex::ROOT,
499-
)
500-
});
501-
502-
self.inject_new_hidden_type_unchecked(key, hidden_ty);
503-
}
504-
}
505475
}
506476

507477
impl<'tcx> Deref for BorrowckInferCtxt<'tcx> {

‎compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+5-164
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,16 @@
11
use rustc_data_structures::fx::FxIndexMap;
2-
use rustc_errors::ErrorGuaranteed;
3-
use rustc_hir::OpaqueTyOrigin;
4-
use rustc_hir::def_id::LocalDefId;
5-
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
6-
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, TyCtxtInferExt as _};
2+
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
73
use rustc_macros::extension;
84
use rustc_middle::ty::{
9-
self, GenericArgKind, GenericArgs, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable,
10-
TypeVisitableExt, TypingMode, fold_regions,
5+
self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions,
116
};
127
use rustc_span::Span;
13-
use rustc_trait_selection::regions::OutlivesEnvironmentBuildExt;
14-
use rustc_trait_selection::traits::ObligationCtxt;
8+
use rustc_trait_selection::opaque_types::check_opaque_type_parameter_valid;
159
use tracing::{debug, instrument};
1610

1711
use super::RegionInferenceContext;
1812
use crate::opaque_types::ConcreteOpaqueTypes;
19-
use crate::session_diagnostics::{LifetimeMismatchOpaqueParam, NonGenericOpaqueTypeParam};
13+
use crate::session_diagnostics::LifetimeMismatchOpaqueParam;
2014
use crate::universal_regions::RegionClassification;
2115

2216
impl<'tcx> RegionInferenceContext<'tcx> {
@@ -273,7 +267,7 @@ impl<'tcx> InferCtxt<'tcx> {
273267
}
274268

275269
if let Err(guar) =
276-
check_opaque_type_parameter_valid(self, opaque_type_key, instantiated_ty.span)
270+
check_opaque_type_parameter_valid(self, opaque_type_key, instantiated_ty.span, false)
277271
{
278272
return Ty::new_error(self.tcx, guar);
279273
}
@@ -289,156 +283,3 @@ impl<'tcx> InferCtxt<'tcx> {
289283
definition_ty
290284
}
291285
}
292-
293-
/// Opaque type parameter validity check as documented in the [rustc-dev-guide chapter].
294-
///
295-
/// [rustc-dev-guide chapter]:
296-
/// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html
297-
fn check_opaque_type_parameter_valid<'tcx>(
298-
infcx: &InferCtxt<'tcx>,
299-
opaque_type_key: OpaqueTypeKey<'tcx>,
300-
span: Span,
301-
) -> Result<(), ErrorGuaranteed> {
302-
let tcx = infcx.tcx;
303-
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
304-
let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id);
305-
let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
306-
307-
for (i, arg) in opaque_type_key.iter_captured_args(tcx) {
308-
let arg_is_param = match arg.unpack() {
309-
GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
310-
GenericArgKind::Lifetime(lt) => {
311-
matches!(*lt, ty::ReEarlyParam(_) | ty::ReLateParam(_))
312-
|| (lt.is_static() && opaque_env.param_equal_static(i))
313-
}
314-
GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)),
315-
};
316-
317-
if arg_is_param {
318-
// Register if the same lifetime appears multiple times in the generic args.
319-
// There is an exception when the opaque type *requires* the lifetimes to be equal.
320-
// See [rustc-dev-guide chapter] § "An exception to uniqueness rule".
321-
let seen_where = seen_params.entry(arg).or_default();
322-
if !seen_where.first().is_some_and(|&prev_i| opaque_env.params_equal(i, prev_i)) {
323-
seen_where.push(i);
324-
}
325-
} else {
326-
// Prevent `fn foo() -> Foo<u32>` from being defining.
327-
let opaque_param = opaque_generics.param_at(i, tcx);
328-
let kind = opaque_param.kind.descr();
329-
330-
opaque_env.param_is_error(i)?;
331-
332-
return Err(infcx.dcx().emit_err(NonGenericOpaqueTypeParam {
333-
ty: arg,
334-
kind,
335-
span,
336-
param_span: tcx.def_span(opaque_param.def_id),
337-
}));
338-
}
339-
}
340-
341-
for (_, indices) in seen_params {
342-
if indices.len() > 1 {
343-
let descr = opaque_generics.param_at(indices[0], tcx).kind.descr();
344-
let spans: Vec<_> = indices
345-
.into_iter()
346-
.map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
347-
.collect();
348-
#[allow(rustc::diagnostic_outside_of_impl)]
349-
#[allow(rustc::untranslatable_diagnostic)]
350-
return Err(infcx
351-
.dcx()
352-
.struct_span_err(span, "non-defining opaque type use in defining scope")
353-
.with_span_note(spans, format!("{descr} used multiple times"))
354-
.emit());
355-
}
356-
}
357-
358-
Ok(())
359-
}
360-
361-
/// Computes if an opaque type requires a lifetime parameter to be equal to
362-
/// another one or to the `'static` lifetime.
363-
/// These requirements are derived from the explicit and implied bounds.
364-
struct LazyOpaqueTyEnv<'tcx> {
365-
tcx: TyCtxt<'tcx>,
366-
def_id: LocalDefId,
367-
368-
/// Equal parameters will have the same name. Computed Lazily.
369-
/// Example:
370-
/// `type Opaque<'a: 'static, 'b: 'c, 'c: 'b> = impl Sized;`
371-
/// Identity args: `['a, 'b, 'c]`
372-
/// Canonical args: `['static, 'b, 'b]`
373-
canonical_args: std::cell::OnceCell<ty::GenericArgsRef<'tcx>>,
374-
}
375-
376-
impl<'tcx> LazyOpaqueTyEnv<'tcx> {
377-
fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
378-
Self { tcx, def_id, canonical_args: std::cell::OnceCell::new() }
379-
}
380-
381-
fn param_equal_static(&self, param_index: usize) -> bool {
382-
self.get_canonical_args()[param_index].expect_region().is_static()
383-
}
384-
385-
fn params_equal(&self, param1: usize, param2: usize) -> bool {
386-
let canonical_args = self.get_canonical_args();
387-
canonical_args[param1] == canonical_args[param2]
388-
}
389-
390-
fn param_is_error(&self, param_index: usize) -> Result<(), ErrorGuaranteed> {
391-
self.get_canonical_args()[param_index].error_reported()
392-
}
393-
394-
fn get_canonical_args(&self) -> ty::GenericArgsRef<'tcx> {
395-
if let Some(&canonical_args) = self.canonical_args.get() {
396-
return canonical_args;
397-
}
398-
399-
let &Self { tcx, def_id, .. } = self;
400-
let origin = tcx.local_opaque_ty_origin(def_id);
401-
let parent = match origin {
402-
OpaqueTyOrigin::FnReturn { parent, .. }
403-
| OpaqueTyOrigin::AsyncFn { parent, .. }
404-
| OpaqueTyOrigin::TyAlias { parent, .. } => parent,
405-
};
406-
let param_env = tcx.param_env(parent);
407-
let args = GenericArgs::identity_for_item(tcx, parent).extend_to(
408-
tcx,
409-
def_id.to_def_id(),
410-
|param, _| {
411-
tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()).into()
412-
},
413-
);
414-
415-
// FIXME(#132279): It feels wrong to use `non_body_analysis` here given that we're
416-
// in a body here.
417-
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
418-
let ocx = ObligationCtxt::new(&infcx);
419-
420-
let wf_tys = ocx.assumed_wf_types(param_env, parent).unwrap_or_else(|_| {
421-
tcx.dcx().span_delayed_bug(tcx.def_span(def_id), "error getting implied bounds");
422-
Default::default()
423-
});
424-
let outlives_env = OutlivesEnvironment::new(&infcx, parent, param_env, wf_tys);
425-
426-
let mut seen = vec![tcx.lifetimes.re_static];
427-
let canonical_args = fold_regions(tcx, args, |r1, _| {
428-
if r1.is_error() {
429-
r1
430-
} else if let Some(&r2) = seen.iter().find(|&&r2| {
431-
let free_regions = outlives_env.free_region_map();
432-
free_regions.sub_free_regions(tcx, r1, r2)
433-
&& free_regions.sub_free_regions(tcx, r2, r1)
434-
}) {
435-
r2
436-
} else {
437-
seen.push(r1);
438-
r1
439-
}
440-
});
441-
self.canonical_args.set(canonical_args).unwrap();
442-
canonical_args
443-
}
444-
}
There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Failed to load comments.