Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions compiler/rustc_borrowck/src/consumers.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@
use rustc_hir::def_id::LocalDefId;
use rustc_index::{IndexSlice, IndexVec};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir::{Body, Promoted};
use rustc_middle::ty::TyCtxt;
use std::rc::Rc;
@@ -105,8 +104,7 @@ pub fn get_body_with_borrowck_facts(
options: ConsumerOptions,
) -> BodyWithBorrowckFacts<'_> {
let (input_body, promoted) = tcx.mir_promoted(def);
let infcx = tcx.infer_ctxt().with_opaque_type_inference(def).build();
let input_body: &Body<'_> = &input_body.borrow();
let promoted: &IndexSlice<_, _> = &promoted.borrow();
*super::do_mir_borrowck(&infcx, input_body, promoted, Some(options)).1.unwrap()
*super::do_mir_borrowck(tcx, input_body, promoted, Some(options)).1.unwrap()
}
62 changes: 43 additions & 19 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
@@ -23,9 +23,8 @@ use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_index::bit_set::{BitSet, ChunkedBitSet};
use rustc_index::{IndexSlice, IndexVec};
use rustc_infer::infer::{
InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::*;
use rustc_middle::query::Providers;
@@ -123,9 +122,8 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
return tcx.arena.alloc(result);
}

let infcx = tcx.infer_ctxt().with_opaque_type_inference(def).build();
let promoted: &IndexSlice<_, _> = &promoted.borrow();
let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, None).0;
let opt_closure_req = do_mir_borrowck(tcx, input_body, promoted, None).0;
debug!("mir_borrowck done");

tcx.arena.alloc(opt_closure_req)
@@ -136,18 +134,15 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
/// Use `consumer_options: None` for the default behavior of returning
/// [`BorrowCheckResult`] only. Otherwise, return [`BodyWithBorrowckFacts`] according
/// to the given [`ConsumerOptions`].
#[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.def_id()), level = "debug")]
#[instrument(skip(tcx, input_body, input_promoted), fields(id=?input_body.source.def_id()), level = "debug")]
fn do_mir_borrowck<'tcx>(
infcx: &InferCtxt<'tcx>,
tcx: TyCtxt<'tcx>,
input_body: &Body<'tcx>,
input_promoted: &IndexSlice<Promoted, Body<'tcx>>,
consumer_options: Option<ConsumerOptions>,
) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
let def = input_body.source.def_id().expect_local();
debug!(?def);

let tcx = infcx.tcx;
let infcx = BorrowckInferCtxt::new(infcx);
let infcx = BorrowckInferCtxt::new(tcx, def);
let param_env = tcx.param_env(def);

let mut local_names = IndexVec::from_elem(None, &input_body.local_decls);
@@ -187,6 +182,12 @@ fn do_mir_borrowck<'tcx>(
nll::replace_regions_in_mir(&infcx, param_env, &mut body_owned, &mut promoted);
let body = &body_owned; // no further changes

// FIXME(-Znext-solver): A bit dubious that we're only registering
// predefined opaques in the typeck root.
if infcx.next_trait_solver() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
infcx.register_predefined_opaques_for_next_solver(def);
}

let location_table = LocationTable::new(body);

let move_data = MoveData::gather_moves(body, tcx, param_env, |_| true);
@@ -440,13 +441,14 @@ fn do_mir_borrowck<'tcx>(
(result, body_with_facts)
}

pub struct BorrowckInferCtxt<'cx, 'tcx> {
pub(crate) infcx: &'cx InferCtxt<'tcx>,
pub struct BorrowckInferCtxt<'tcx> {
pub(crate) infcx: InferCtxt<'tcx>,
pub(crate) reg_var_to_origin: RefCell<FxIndexMap<ty::RegionVid, RegionCtxt>>,
}

impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> {
pub(crate) fn new(infcx: &'cx InferCtxt<'tcx>) -> Self {
impl<'tcx> BorrowckInferCtxt<'tcx> {
pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
let infcx = tcx.infer_ctxt().with_opaque_type_inference(def_id).build();
BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()) }
}

@@ -492,18 +494,40 @@ impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> {

next_region
}

/// With the new solver we prepopulate the opaque type storage during
/// MIR borrowck with the hidden types from HIR typeck. This is necessary
/// to avoid ambiguities as earlier goals can rely on the hidden type
/// of an opaque which is only constrained by a later goal.
fn register_predefined_opaques_for_next_solver(&self, def_id: LocalDefId) {
let tcx = self.tcx;
// OK to use the identity arguments for each opaque type key, since
// we remap opaques from HIR typeck back to their definition params.
for data in tcx.typeck(def_id).concrete_opaque_types.iter().map(|(k, v)| (*k, *v)) {
// HIR typeck did not infer the regions of the opaque, so we instantiate
// them with fresh inference variables.
let (key, hidden_ty) = tcx.fold_regions(data, |_, _| {
self.next_nll_region_var_in_universe(
NllRegionVariableOrigin::Existential { from_forall: false },
ty::UniverseIndex::ROOT,
)
});

self.inject_new_hidden_type_unchecked(key, hidden_ty);
}
}
}

impl<'cx, 'tcx> Deref for BorrowckInferCtxt<'cx, 'tcx> {
impl<'tcx> Deref for BorrowckInferCtxt<'tcx> {
type Target = InferCtxt<'tcx>;

fn deref(&self) -> &'cx Self::Target {
self.infcx
fn deref(&self) -> &Self::Target {
&self.infcx
}
}

struct MirBorrowckCtxt<'cx, 'tcx> {
infcx: &'cx BorrowckInferCtxt<'cx, 'tcx>,
infcx: &'cx BorrowckInferCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
body: &'cx Body<'tcx>,
move_data: &'cx MoveData<'tcx>,
8 changes: 4 additions & 4 deletions compiler/rustc_borrowck/src/nll.rs
Original file line number Diff line number Diff line change
@@ -51,7 +51,7 @@ pub(crate) struct NllOutput<'tcx> {
/// `compute_regions`.
#[instrument(skip(infcx, param_env, body, promoted), level = "debug")]
pub(crate) fn replace_regions_in_mir<'tcx>(
infcx: &BorrowckInferCtxt<'_, 'tcx>,
infcx: &BorrowckInferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &mut Body<'tcx>,
promoted: &mut IndexSlice<Promoted, Body<'tcx>>,
@@ -75,7 +75,7 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
///
/// This may result in errors being reported.
pub(crate) fn compute_regions<'cx, 'tcx>(
infcx: &BorrowckInferCtxt<'_, 'tcx>,
infcx: &BorrowckInferCtxt<'tcx>,
universal_regions: UniversalRegions<'tcx>,
body: &Body<'tcx>,
promoted: &IndexSlice<Promoted, Body<'tcx>>,
@@ -202,7 +202,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
}

pub(super) fn dump_mir_results<'tcx>(
infcx: &BorrowckInferCtxt<'_, 'tcx>,
infcx: &BorrowckInferCtxt<'tcx>,
body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
@@ -254,7 +254,7 @@ pub(super) fn dump_mir_results<'tcx>(
#[allow(rustc::diagnostic_outside_of_impl)]
#[allow(rustc::untranslatable_diagnostic)]
pub(super) fn dump_annotation<'tcx>(
infcx: &BorrowckInferCtxt<'_, 'tcx>,
infcx: &BorrowckInferCtxt<'tcx>,
body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
9 changes: 3 additions & 6 deletions compiler/rustc_borrowck/src/region_infer/mod.rs
Original file line number Diff line number Diff line change
@@ -250,10 +250,7 @@ pub enum ExtraConstraintInfo {
}

#[instrument(skip(infcx, sccs), level = "debug")]
fn sccs_info<'cx, 'tcx>(
infcx: &'cx BorrowckInferCtxt<'cx, 'tcx>,
sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
) {
fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>) {
use crate::renumber::RegionCtxt;

let var_to_origin = infcx.reg_var_to_origin.borrow();
@@ -322,8 +319,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
///
/// The `outlives_constraints` and `type_tests` are an initial set
/// of constraints produced by the MIR type check.
pub(crate) fn new<'cx>(
_infcx: &BorrowckInferCtxt<'cx, 'tcx>,
pub(crate) fn new(
_infcx: &BorrowckInferCtxt<'tcx>,
var_infos: VarInfos,
universal_regions: Rc<UniversalRegions<'tcx>>,
placeholder_indices: Rc<PlaceholderIndices>,
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/renumber.rs
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ use rustc_span::Symbol;
/// inference variables, returning the number of variables created.
#[instrument(skip(infcx, body, promoted), level = "debug")]
pub fn renumber_mir<'tcx>(
infcx: &BorrowckInferCtxt<'_, 'tcx>,
infcx: &BorrowckInferCtxt<'tcx>,
body: &mut Body<'tcx>,
promoted: &mut IndexSlice<Promoted, Body<'tcx>>,
) {
@@ -57,7 +57,7 @@ impl RegionCtxt {
}

struct RegionRenumberer<'a, 'tcx> {
infcx: &'a BorrowckInferCtxt<'a, 'tcx>,
infcx: &'a BorrowckInferCtxt<'tcx>,
}

impl<'a, 'tcx> RegionRenumberer<'a, 'tcx> {
77 changes: 4 additions & 73 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
@@ -24,7 +24,6 @@ use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::cast::CastTy;
use rustc_middle::ty::visit::TypeVisitableExt;
@@ -122,7 +121,7 @@ mod relate_tys;
/// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis
/// - `elements` -- MIR region map
pub(crate) fn type_check<'mir, 'tcx>(
infcx: &BorrowckInferCtxt<'_, 'tcx>,
infcx: &BorrowckInferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>,
promoted: &IndexSlice<Promoted, Body<'tcx>>,
@@ -865,7 +864,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
/// way, it accrues region constraints -- these can later be used by
/// NLL region checking.
struct TypeChecker<'a, 'tcx> {
infcx: &'a BorrowckInferCtxt<'a, 'tcx>,
infcx: &'a BorrowckInferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
last_span: Span,
body: &'a Body<'tcx>,
@@ -1020,15 +1019,15 @@ impl Locations {

impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
fn new(
infcx: &'a BorrowckInferCtxt<'a, 'tcx>,
infcx: &'a BorrowckInferCtxt<'tcx>,
body: &'a Body<'tcx>,
param_env: ty::ParamEnv<'tcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
implicit_region_bound: ty::Region<'tcx>,
borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
) -> Self {
let mut checker = Self {
Self {
infcx,
last_span: body.span,
body,
@@ -1039,74 +1038,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
implicit_region_bound,
borrowck_context,
reported_errors: Default::default(),
};

// FIXME(-Znext-solver): A bit dubious that we're only registering
// predefined opaques in the typeck root.
if infcx.next_trait_solver() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
checker.register_predefined_opaques_for_next_solver();
}

checker
}

pub(super) fn register_predefined_opaques_for_next_solver(&mut self) {
// OK to use the identity arguments for each opaque type key, since
// we remap opaques from HIR typeck back to their definition params.
let opaques: Vec<_> = self
.infcx
.tcx
.typeck(self.body.source.def_id().expect_local())
.concrete_opaque_types
.iter()
.map(|(k, v)| (*k, *v))
.collect();

let renumbered_opaques = self.infcx.tcx.fold_regions(opaques, |_, _| {
self.infcx.next_nll_region_var_in_universe(
NllRegionVariableOrigin::Existential { from_forall: false },
ty::UniverseIndex::ROOT,
)
});

let param_env = self.param_env;
let result = self.fully_perform_op(
Locations::All(self.body.span),
ConstraintCategory::OpaqueType,
CustomTypeOp::new(
|ocx| {
let mut obligations = Vec::new();
for (opaque_type_key, hidden_ty) in renumbered_opaques {
let cause = ObligationCause::dummy();
ocx.infcx.insert_hidden_type(
opaque_type_key,
&cause,
param_env,
hidden_ty.ty,
&mut obligations,
)?;

ocx.infcx.add_item_bounds_for_hidden_type(
opaque_type_key.def_id.to_def_id(),
opaque_type_key.args,
cause,
param_env,
hidden_ty.ty,
&mut obligations,
);
}

ocx.register_obligations(obligations);
Ok(())
},
"register pre-defined opaques",
),
);

if result.is_err() {
self.infcx
.dcx()
.span_bug(self.body.span, "failed re-defining predefined opaques in mir typeck");
}
}

6 changes: 3 additions & 3 deletions compiler/rustc_borrowck/src/universal_regions.rs
Original file line number Diff line number Diff line change
@@ -240,7 +240,7 @@ impl<'tcx> UniversalRegions<'tcx> {
/// signature. This will also compute the relationships that are
/// known between those regions.
pub fn new(
infcx: &BorrowckInferCtxt<'_, 'tcx>,
infcx: &BorrowckInferCtxt<'tcx>,
mir_def: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
) -> Self {
@@ -411,7 +411,7 @@ impl<'tcx> UniversalRegions<'tcx> {
}

struct UniversalRegionsBuilder<'cx, 'tcx> {
infcx: &'cx BorrowckInferCtxt<'cx, 'tcx>,
infcx: &'cx BorrowckInferCtxt<'tcx>,
mir_def: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
}
@@ -796,7 +796,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
}

#[extension(trait InferCtxtExt<'tcx>)]
impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> {
impl<'tcx> BorrowckInferCtxt<'tcx> {
#[instrument(skip(self), level = "debug")]
fn replace_free_regions_with_nll_infer_vars<T>(
&self,
13 changes: 13 additions & 0 deletions compiler/rustc_infer/src/infer/opaque_types/mod.rs
Original file line number Diff line number Diff line change
@@ -485,6 +485,19 @@ impl<'tcx> InferCtxt<'tcx> {
Ok(InferOk { value: (), obligations })
}

/// Insert a hidden type into the opaque type storage, making sure
/// it hasn't previously been defined. This does not emit any
/// constraints and it's the responsibility of the caller to make
/// sure that the item bounds of the opaque are checked.
pub fn inject_new_hidden_type_unchecked(
&self,
opaque_type_key: OpaqueTypeKey<'tcx>,
hidden_ty: OpaqueHiddenType<'tcx>,
) {
let prev = self.inner.borrow_mut().opaque_types().register(opaque_type_key, hidden_ty);
assert_eq!(prev, None);
}

/// Insert a hidden type into the opaque type storage, equating it
/// with any previous entries if necessary.
///
11 changes: 4 additions & 7 deletions compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
Original file line number Diff line number Diff line change
@@ -236,7 +236,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
normalization_nested_goals,
} = external_constraints.deref();
self.register_region_constraints(region_constraints);
self.register_new_opaque_types(param_env, opaque_types);
self.register_new_opaque_types(opaque_types);
(normalization_nested_goals.clone(), certainty)
}

@@ -368,13 +368,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
assert!(region_constraints.member_constraints.is_empty());
}

fn register_new_opaque_types(
&mut self,
param_env: ty::ParamEnv<'tcx>,
opaque_types: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)],
) {
fn register_new_opaque_types(&mut self, opaque_types: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)]) {
for &(key, ty) in opaque_types {
self.insert_hidden_type(key, param_env, ty).unwrap();
let hidden_ty = ty::OpaqueHiddenType { ty, span: DUMMY_SP };
self.infcx.inject_new_hidden_type_unchecked(key, hidden_ty);
}
}
}
4 changes: 2 additions & 2 deletions compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
Original file line number Diff line number Diff line change
@@ -248,8 +248,8 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
};

for &(key, ty) in &input.predefined_opaques_in_body.opaque_types {
ecx.insert_hidden_type(key, input.goal.param_env, ty)
.expect("failed to prepopulate opaque types");
let hidden_ty = ty::OpaqueHiddenType { ty, span: DUMMY_SP };
ecx.infcx.inject_new_hidden_type_unchecked(key, hidden_ty);
}

if !ecx.nested_goals.is_empty() {
3 changes: 3 additions & 0 deletions tests/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs
Original file line number Diff line number Diff line change
@@ -2,6 +2,9 @@
// when there are multiple inputs. The `dyn Bar` should default to `+
// 'static`. This used to erroneously generate an error (cc #62517).
//
//@ revisions: current next
//@[next] compile-flags: -Znext-solver
//@ ignore-compare-mode-next-solver (explicit revisions)
//@ check-pass

trait Foo {
3 changes: 3 additions & 0 deletions tests/ui/impl-trait/in-trait/placeholder-implied-bounds.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//@ revisions: current next
//@[next] compile-flags: -Znext-solver
//@ ignore-compare-mode-next-solver (explicit revisions)
//@ check-pass

pub fn main() {}
3 changes: 3 additions & 0 deletions tests/ui/impl-trait/issues/issue-105826.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//@ revisions: current next
//@[next] compile-flags: -Znext-solver
//@ ignore-compare-mode-next-solver (explicit revisions)
//@ check-pass

use std::io::Write;

This file was deleted.

29 changes: 0 additions & 29 deletions tests/ui/traits/trait-upcasting/illegal-upcast-from-impl-opaque.rs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error[E0308]: mismatched types
--> $DIR/illegal-upcast-from-impl-opaque.rs:26:5
--> $DIR/upcast-defining-opaque.rs:21:5
|
LL | type Foo = impl Sized;
| ---------- the found opaque type
LL |
LL | fn illegal(x: &dyn Sub<Assoc = Foo>) -> &dyn Super<Assoc = i32> {
| ----------------------- expected `&dyn Super<Assoc = i32>` because of return type
LL | fn upcast(x: &dyn Sub<Assoc = Foo>) -> &dyn Super<Assoc = i32> {
| ----------------------- expected `&dyn Super<Assoc = i32>` because of return type
LL | x
| ^ expected trait `Super`, found trait `Sub`
|
24 changes: 24 additions & 0 deletions tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//@ revisions: current next
//@[next] compile-flags: -Znext-solver
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] check-pass

#![feature(trait_upcasting, type_alias_impl_trait)]

trait Super {
type Assoc;
}

trait Sub: Super {}

impl<T: ?Sized> Super for T {
type Assoc = i32;
}

type Foo = impl Sized;

fn upcast(x: &dyn Sub<Assoc = Foo>) -> &dyn Super<Assoc = i32> {
x //[current]~ mismatched types
}

fn main() {}