Skip to content

Commit f132bcf

Browse files
committed
Auto merge of #94081 - oli-obk:lazy_tait_take_two, r=nikomatsakis
Lazy type-alias-impl-trait take two ### user visible change 1: RPIT inference from recursive call sites Lazy TAIT has an insta-stable change. The following snippet now compiles, because opaque types can now have their hidden type set from wherever the opaque type is mentioned. ```rust fn bar(b: bool) -> impl std::fmt::Debug { if b { return 42 } let x: u32 = bar(false); // this errors on stable 99 } ``` The return type of `bar` stays opaque, you can't do `bar(false) + 42`, you need to actually mention the hidden type. ### user visible change 2: divergence between RPIT and TAIT in return statements Note that `return` statements and the trailing return expression are special with RPIT (but not TAIT). So ```rust #![feature(type_alias_impl_trait)] type Foo = impl std::fmt::Debug; fn foo(b: bool) -> Foo { if b { return vec![42]; } std::iter::empty().collect() //~ ERROR `Foo` cannot be built from an iterator } fn bar(b: bool) -> impl std::fmt::Debug { if b { return vec![42] } std::iter::empty().collect() // Works, magic (accidentally stabilized, not intended) } ``` But when we are working with the return value of a recursive call, the behavior of RPIT and TAIT is the same: ```rust type Foo = impl std::fmt::Debug; fn foo(b: bool) -> Foo { if b { return vec![]; } let mut x = foo(false); x = std::iter::empty().collect(); //~ ERROR `Foo` cannot be built from an iterator vec![] } fn bar(b: bool) -> impl std::fmt::Debug { if b { return vec![]; } let mut x = bar(false); x = std::iter::empty().collect(); //~ ERROR `impl Debug` cannot be built from an iterator vec![] } ``` ### user visible change 3: TAIT does not merge types across branches In contrast to RPIT, TAIT does not merge types across branches, so the following does not compile. ```rust type Foo = impl std::fmt::Debug; fn foo(b: bool) -> Foo { if b { vec![42_i32] } else { std::iter::empty().collect() //~^ ERROR `Foo` cannot be built from an iterator over elements of type `_` } } ``` It is easy to support, but we should make an explicit decision to include the additional complexity in the implementation (it's not much, see a721052457cf513487fb4266e3ade65c29b272d2 which needs to be reverted to enable this). ### PR formalities previous attempt: #92007 This PR also includes #92306 and #93783, as they were reverted along with #92007 in #93893 fixes #93411 fixes #88236 fixes #89312 fixes #87340 fixes #86800 fixes #86719 fixes #84073 fixes #83919 fixes #82139 fixes #77987 fixes #74282 fixes #67830 fixes #62742 fixes #54895
2 parents 1446d17 + 638f84d commit f132bcf

File tree

419 files changed

+5204
-2486
lines changed

Some content is hidden

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

419 files changed

+5204
-2486
lines changed

compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs

+91-21
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@ use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
22
use rustc_infer::infer::canonical::Canonical;
33
use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError;
44
use rustc_infer::infer::region_constraints::Constraint;
5+
use rustc_infer::infer::region_constraints::RegionConstraintData;
6+
use rustc_infer::infer::RegionVariableOrigin;
57
use rustc_infer::infer::{InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt as _};
68
use rustc_infer::traits::{Normalized, ObligationCause, TraitEngine, TraitEngineExt};
79
use rustc_middle::ty::error::TypeError;
10+
use rustc_middle::ty::RegionVid;
11+
use rustc_middle::ty::UniverseIndex;
812
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
913
use rustc_span::Span;
1014
use rustc_trait_selection::traits::query::type_op;
@@ -76,6 +80,15 @@ crate trait ToUniverseInfo<'tcx> {
7680
fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx>;
7781
}
7882

83+
impl<'tcx> ToUniverseInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
84+
fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
85+
UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(crate::type_check::InstantiateOpaqueType {
86+
base_universe: Some(base_universe),
87+
..self
88+
})))
89+
}
90+
}
91+
7992
impl<'tcx> ToUniverseInfo<'tcx>
8093
for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>>
8194
{
@@ -116,6 +129,12 @@ impl<'tcx, F, G> ToUniverseInfo<'tcx> for Canonical<'tcx, type_op::custom::Custo
116129
}
117130
}
118131

132+
impl<'tcx> ToUniverseInfo<'tcx> for ! {
133+
fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
134+
self
135+
}
136+
}
137+
119138
#[allow(unused_lifetimes)]
120139
trait TypeOpInfo<'tcx> {
121140
/// Returns an error to be reported if rerunning the type op fails to
@@ -130,7 +149,7 @@ trait TypeOpInfo<'tcx> {
130149

131150
fn nice_error(
132151
&self,
133-
tcx: TyCtxt<'tcx>,
152+
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
134153
cause: ObligationCause<'tcx>,
135154
placeholder_region: ty::Region<'tcx>,
136155
error_region: Option<ty::Region<'tcx>>,
@@ -175,7 +194,7 @@ trait TypeOpInfo<'tcx> {
175194
debug!(?placeholder_region);
176195

177196
let span = cause.span;
178-
let nice_error = self.nice_error(tcx, cause, placeholder_region, error_region);
197+
let nice_error = self.nice_error(mbcx, cause, placeholder_region, error_region);
179198

180199
if let Some(nice_error) = nice_error {
181200
mbcx.buffer_error(nice_error);
@@ -208,16 +227,16 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
208227

209228
fn nice_error(
210229
&self,
211-
tcx: TyCtxt<'tcx>,
230+
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
212231
cause: ObligationCause<'tcx>,
213232
placeholder_region: ty::Region<'tcx>,
214233
error_region: Option<ty::Region<'tcx>>,
215234
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
216-
tcx.infer_ctxt().enter_with_canonical(
235+
mbcx.infcx.tcx.infer_ctxt().enter_with_canonical(
217236
cause.span,
218237
&self.canonical_query,
219238
|ref infcx, key, _| {
220-
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
239+
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
221240
type_op_prove_predicate_with_cause(infcx, &mut *fulfill_cx, key, cause);
222241
try_extract_error_from_fulfill_cx(
223242
fulfill_cx,
@@ -255,16 +274,16 @@ where
255274

256275
fn nice_error(
257276
&self,
258-
tcx: TyCtxt<'tcx>,
277+
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
259278
cause: ObligationCause<'tcx>,
260279
placeholder_region: ty::Region<'tcx>,
261280
error_region: Option<ty::Region<'tcx>>,
262281
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
263-
tcx.infer_ctxt().enter_with_canonical(
282+
mbcx.infcx.tcx.infer_ctxt().enter_with_canonical(
264283
cause.span,
265284
&self.canonical_query,
266285
|ref infcx, key, _| {
267-
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
286+
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
268287

269288
let mut selcx = SelectionContext::new(infcx);
270289

@@ -316,16 +335,16 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
316335

317336
fn nice_error(
318337
&self,
319-
tcx: TyCtxt<'tcx>,
338+
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
320339
cause: ObligationCause<'tcx>,
321340
placeholder_region: ty::Region<'tcx>,
322341
error_region: Option<ty::Region<'tcx>>,
323342
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
324-
tcx.infer_ctxt().enter_with_canonical(
343+
mbcx.infcx.tcx.infer_ctxt().enter_with_canonical(
325344
cause.span,
326345
&self.canonical_query,
327346
|ref infcx, key, _| {
328-
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
347+
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
329348
type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(cause.span))
330349
.ok()?;
331350
try_extract_error_from_fulfill_cx(
@@ -339,43 +358,94 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
339358
}
340359
}
341360

361+
impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
362+
fn fallback_error(
363+
&self,
364+
tcx: TyCtxt<'tcx>,
365+
span: Span,
366+
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
367+
// FIXME: This error message isn't great, but it doesn't show up in the existing UI tests,
368+
// and is only the fallback when the nice error fails. Consider improving this some more.
369+
tcx.sess.struct_span_err(span, "higher-ranked lifetime error for opaque type!")
370+
}
371+
372+
fn base_universe(&self) -> ty::UniverseIndex {
373+
self.base_universe.unwrap()
374+
}
375+
376+
fn nice_error(
377+
&self,
378+
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
379+
_cause: ObligationCause<'tcx>,
380+
placeholder_region: ty::Region<'tcx>,
381+
error_region: Option<ty::Region<'tcx>>,
382+
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
383+
try_extract_error_from_region_constraints(
384+
mbcx.infcx,
385+
placeholder_region,
386+
error_region,
387+
self.region_constraints.as_ref().unwrap(),
388+
// We're using the original `InferCtxt` that we
389+
// started MIR borrowchecking with, so the region
390+
// constraints have already been taken. Use the data from
391+
// our `mbcx` instead.
392+
|vid| mbcx.regioncx.var_infos[vid].origin,
393+
|vid| mbcx.regioncx.var_infos[vid].universe,
394+
)
395+
}
396+
}
397+
342398
#[instrument(skip(fulfill_cx, infcx), level = "debug")]
343399
fn try_extract_error_from_fulfill_cx<'tcx>(
344400
mut fulfill_cx: Box<dyn TraitEngine<'tcx> + 'tcx>,
345401
infcx: &InferCtxt<'_, 'tcx>,
346402
placeholder_region: ty::Region<'tcx>,
347403
error_region: Option<ty::Region<'tcx>>,
348404
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
349-
let tcx = infcx.tcx;
350-
351405
// We generally shouldn't have errors here because the query was
352406
// already run, but there's no point using `delay_span_bug`
353407
// when we're going to emit an error here anyway.
354408
let _errors = fulfill_cx.select_all_or_error(infcx);
409+
let region_constraints = infcx.with_region_constraints(|r| r.clone());
410+
try_extract_error_from_region_constraints(
411+
infcx,
412+
placeholder_region,
413+
error_region,
414+
&region_constraints,
415+
|vid| infcx.region_var_origin(vid),
416+
|vid| infcx.universe_of_region(infcx.tcx.mk_region(ty::ReVar(vid))),
417+
)
418+
}
355419

356-
let (sub_region, cause) = infcx.with_region_constraints(|region_constraints| {
357-
debug!("{:#?}", region_constraints);
420+
fn try_extract_error_from_region_constraints<'tcx>(
421+
infcx: &InferCtxt<'_, 'tcx>,
422+
placeholder_region: ty::Region<'tcx>,
423+
error_region: Option<ty::Region<'tcx>>,
424+
region_constraints: &RegionConstraintData<'tcx>,
425+
mut region_var_origin: impl FnMut(RegionVid) -> RegionVariableOrigin,
426+
mut universe_of_region: impl FnMut(RegionVid) -> UniverseIndex,
427+
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
428+
let (sub_region, cause) =
358429
region_constraints.constraints.iter().find_map(|(constraint, cause)| {
359430
match *constraint {
360431
Constraint::RegSubReg(sub, sup) if sup == placeholder_region && sup != sub => {
361432
Some((sub, cause.clone()))
362433
}
363434
// FIXME: Should this check the universe of the var?
364435
Constraint::VarSubReg(vid, sup) if sup == placeholder_region => {
365-
Some((tcx.mk_region(ty::ReVar(vid)), cause.clone()))
436+
Some((infcx.tcx.mk_region(ty::ReVar(vid)), cause.clone()))
366437
}
367438
_ => None,
368439
}
369-
})
370-
})?;
440+
})?;
371441

372442
debug!(?sub_region, "cause = {:#?}", cause);
373443
let nice_error = match (error_region, *sub_region) {
374444
(Some(error_region), ty::ReVar(vid)) => NiceRegionError::new(
375445
infcx,
376446
RegionResolutionError::SubSupConflict(
377447
vid,
378-
infcx.region_var_origin(vid),
448+
region_var_origin(vid),
379449
cause.clone(),
380450
error_region,
381451
cause.clone(),
@@ -392,8 +462,8 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
392462
infcx,
393463
RegionResolutionError::UpperBoundUniverseConflict(
394464
vid,
395-
infcx.region_var_origin(vid),
396-
infcx.universe_of_region(sub_region),
465+
region_var_origin(vid),
466+
universe_of_region(vid),
397467
cause.clone(),
398468
placeholder_region,
399469
),

compiler/rustc_borrowck/src/lib.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#![feature(let_chains)]
88
#![feature(let_else)]
99
#![feature(min_specialization)]
10+
#![feature(never_type)]
1011
#![feature(stmt_expr_attributes)]
1112
#![feature(trusted_step)]
1213
#![feature(try_blocks)]
@@ -125,8 +126,9 @@ fn mir_borrowck<'tcx>(
125126
) -> &'tcx BorrowCheckResult<'tcx> {
126127
let (input_body, promoted) = tcx.mir_promoted(def);
127128
debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
129+
let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;
128130

129-
let opt_closure_req = tcx.infer_ctxt().with_opaque_type_inference(def.did).enter(|infcx| {
131+
let opt_closure_req = tcx.infer_ctxt().with_opaque_type_inference(hir_owner).enter(|infcx| {
130132
let input_body: &Body<'_> = &input_body.borrow();
131133
let promoted: &IndexVec<_, _> = &promoted.borrow();
132134
do_mir_borrowck(&infcx, input_body, promoted, false).0
@@ -141,7 +143,7 @@ fn mir_borrowck<'tcx>(
141143
/// If `return_body_with_facts` is true, then return the body with non-erased
142144
/// region ids on which the borrow checking was performed together with Polonius
143145
/// facts.
144-
#[instrument(skip(infcx, input_body, input_promoted), level = "debug")]
146+
#[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.with_opt_param().as_local().unwrap()), level = "debug")]
145147
fn do_mir_borrowck<'a, 'tcx>(
146148
infcx: &InferCtxt<'a, 'tcx>,
147149
input_body: &Body<'tcx>,

compiler/rustc_borrowck/src/nll.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_middle::mir::{
88
BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location,
99
Promoted,
1010
};
11-
use rustc_middle::ty::{self, OpaqueTypeKey, Region, RegionVid, Ty};
11+
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Region, RegionVid};
1212
use rustc_span::symbol::sym;
1313
use std::env;
1414
use std::fmt::Debug;
@@ -43,7 +43,7 @@ pub type PoloniusOutput = Output<RustcFacts>;
4343
/// closure requirements to propagate, and any generated errors.
4444
crate struct NllOutput<'tcx> {
4545
pub regioncx: RegionInferenceContext<'tcx>,
46-
pub opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
46+
pub opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
4747
pub polonius_input: Option<Box<AllFacts>>,
4848
pub polonius_output: Option<Rc<PoloniusOutput>>,
4949
pub opt_closure_req: Option<ClosureRegionRequirements<'tcx>>,
@@ -305,7 +305,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
305305
infcx.set_tainted_by_errors();
306306
}
307307

308-
let remapped_opaque_tys = regioncx.infer_opaque_types(&infcx, opaque_type_values, body.span);
308+
let remapped_opaque_tys = regioncx.infer_opaque_types(&infcx, opaque_type_values);
309309

310310
NllOutput {
311311
regioncx,
@@ -372,7 +372,7 @@ pub(super) fn dump_annotation<'a, 'tcx>(
372372
body: &Body<'tcx>,
373373
regioncx: &RegionInferenceContext<'tcx>,
374374
closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
375-
opaque_type_values: &VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
375+
opaque_type_values: &VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
376376
errors: &mut crate::error::BorrowckErrors<'tcx>,
377377
) {
378378
let tcx = infcx.tcx;

compiler/rustc_borrowck/src/region_infer/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ mod reverse_sccs;
4545
pub mod values;
4646

4747
pub struct RegionInferenceContext<'tcx> {
48+
pub var_infos: VarInfos,
4849
/// Contains the definition for every region variable. Region
4950
/// variables are identified by their index (`RegionVid`). The
5051
/// definition contains information about where the region came
@@ -267,7 +268,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
267268
) -> Self {
268269
// Create a RegionDefinition for each inference variable.
269270
let definitions: IndexVec<_, _> = var_infos
270-
.into_iter()
271+
.iter()
271272
.map(|info| RegionDefinition::new(info.universe, info.origin))
272273
.collect();
273274

@@ -292,6 +293,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
292293
Rc::new(member_constraints_in.into_mapped(|r| constraint_sccs.scc(r)));
293294

294295
let mut result = Self {
296+
var_infos,
295297
definitions,
296298
liveness_constraints,
297299
constraints,

0 commit comments

Comments
 (0)