summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_borrowck
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_borrowck')
-rw-r--r--compiler/rustc_borrowck/Cargo.toml1
-rw-r--r--compiler/rustc_borrowck/src/constraint_generation.rs12
-rw-r--r--compiler/rustc_borrowck/src/consumers.rs9
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs152
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs148
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs156
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs16
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs5
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs12
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs109
-rw-r--r--compiler/rustc_borrowck/src/lib.rs22
-rw-r--r--compiler/rustc_borrowck/src/nll.rs14
-rw-r--r--compiler/rustc_borrowck/src/places_conflict.rs13
-rw-r--r--compiler/rustc_borrowck/src/prefixes.rs1
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs41
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs374
-rw-r--r--compiler/rustc_borrowck/src/renumber.rs32
-rw-r--r--compiler/rustc_borrowck/src/session_diagnostics.rs71
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs17
-rw-r--r--compiler/rustc_borrowck/src/type_check/constraint_conversion.rs4
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs17
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs39
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs156
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs19
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs10
26 files changed, 643 insertions, 809 deletions
diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml
index fbf628e86..87c113f3e 100644
--- a/compiler/rustc_borrowck/Cargo.toml
+++ b/compiler/rustc_borrowck/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
either = "1.5.0"
diff --git a/compiler/rustc_borrowck/src/constraint_generation.rs b/compiler/rustc_borrowck/src/constraint_generation.rs
index 144fd15fc..f185e402f 100644
--- a/compiler/rustc_borrowck/src/constraint_generation.rs
+++ b/compiler/rustc_borrowck/src/constraint_generation.rs
@@ -14,8 +14,8 @@ use crate::{
places_conflict, region_infer::values::LivenessValues,
};
-pub(super) fn generate_constraints<'cx, 'tcx>(
- infcx: &InferCtxt<'cx, 'tcx>,
+pub(super) fn generate_constraints<'tcx>(
+ infcx: &InferCtxt<'tcx>,
liveness_constraints: &mut LivenessValues<RegionVid>,
all_facts: &mut Option<AllFacts>,
location_table: &LocationTable,
@@ -37,8 +37,8 @@ pub(super) fn generate_constraints<'cx, 'tcx>(
}
/// 'cg = the duration of the constraint generation process itself.
-struct ConstraintGeneration<'cg, 'cx, 'tcx> {
- infcx: &'cg InferCtxt<'cx, 'tcx>,
+struct ConstraintGeneration<'cg, 'tcx> {
+ infcx: &'cg InferCtxt<'tcx>,
all_facts: &'cg mut Option<AllFacts>,
location_table: &'cg LocationTable,
liveness_constraints: &'cg mut LivenessValues<RegionVid>,
@@ -46,7 +46,7 @@ struct ConstraintGeneration<'cg, 'cx, 'tcx> {
body: &'cg Body<'tcx>,
}
-impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> {
+impl<'cg, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'tcx> {
fn visit_basic_block_data(&mut self, bb: BasicBlock, data: &BasicBlockData<'tcx>) {
self.super_basic_block_data(bb, data);
}
@@ -156,7 +156,7 @@ impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> {
}
}
-impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> {
+impl<'cx, 'tcx> ConstraintGeneration<'cx, 'tcx> {
/// Some variable with type `live_ty` is "regular live" at
/// `location` -- i.e., it may be used later. This means that all
/// regions appearing in the type `live_ty` must be live at
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs
index efc17a173..b162095f8 100644
--- a/compiler/rustc_borrowck/src/consumers.rs
+++ b/compiler/rustc_borrowck/src/consumers.rs
@@ -31,9 +31,8 @@ pub fn get_body_with_borrowck_facts<'tcx>(
def: ty::WithOptConstParam<LocalDefId>,
) -> BodyWithBorrowckFacts<'tcx> {
let (input_body, promoted) = tcx.mir_promoted(def);
- tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def.did)).enter(|infcx| {
- let input_body: &Body<'_> = &input_body.borrow();
- let promoted: &IndexVec<_, _> = &promoted.borrow();
- *super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap()
- })
+ let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def.did)).build();
+ let input_body: &Body<'_> = &input_body.borrow();
+ let promoted: &IndexVec<_, _> = &promoted.borrow();
+ *super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap()
}
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index b1def1892..02071ed6b 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -56,7 +56,7 @@ impl<'tcx> UniverseInfo<'tcx> {
) {
match self.0 {
UniverseInfoInner::RelateTys { expected, found } => {
- let err = mbcx.infcx.report_mismatched_types(
+ let err = mbcx.infcx.err_ctxt().report_mismatched_types(
&cause,
expected,
found,
@@ -238,20 +238,11 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
- mbcx.infcx.tcx.infer_ctxt().enter_with_canonical(
- cause.span,
- &self.canonical_query,
- |ref infcx, key, _| {
- let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
- type_op_prove_predicate_with_cause(infcx, &mut *fulfill_cx, key, cause);
- try_extract_error_from_fulfill_cx(
- fulfill_cx,
- infcx,
- placeholder_region,
- error_region,
- )
- },
- )
+ let (ref infcx, key, _) =
+ mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
+ let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
+ type_op_prove_predicate_with_cause(infcx, &mut *fulfill_cx, key, cause);
+ try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
}
}
@@ -288,37 +279,24 @@ where
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
- mbcx.infcx.tcx.infer_ctxt().enter_with_canonical(
- cause.span,
- &self.canonical_query,
- |ref infcx, key, _| {
- let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
-
- let mut selcx = SelectionContext::new(infcx);
-
- // FIXME(lqd): Unify and de-duplicate the following with the actual
- // `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the
- // `ObligationCause`. The normalization results are currently different between
- // `AtExt::normalize` used in the query and `normalize` called below: the former fails
- // to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. Check
- // after #85499 lands to see if its fixes have erased this difference.
- let (param_env, value) = key.into_parts();
- let Normalized { value: _, obligations } = rustc_trait_selection::traits::normalize(
- &mut selcx,
- param_env,
- cause,
- value.value,
- );
- fulfill_cx.register_predicate_obligations(infcx, obligations);
-
- try_extract_error_from_fulfill_cx(
- fulfill_cx,
- infcx,
- placeholder_region,
- error_region,
- )
- },
- )
+ let (ref infcx, key, _) =
+ mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
+ let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
+
+ let mut selcx = SelectionContext::new(infcx);
+
+ // FIXME(lqd): Unify and de-duplicate the following with the actual
+ // `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the
+ // `ObligationCause`. The normalization results are currently different between
+ // `AtExt::normalize` used in the query and `normalize` called below: the former fails
+ // to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. Check
+ // after #85499 lands to see if its fixes have erased this difference.
+ let (param_env, value) = key.into_parts();
+ let Normalized { value: _, obligations } =
+ rustc_trait_selection::traits::normalize(&mut selcx, param_env, cause, value.value);
+ fulfill_cx.register_predicate_obligations(infcx, obligations);
+
+ try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
}
}
@@ -349,21 +327,11 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
- mbcx.infcx.tcx.infer_ctxt().enter_with_canonical(
- cause.span,
- &self.canonical_query,
- |ref infcx, key, _| {
- let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
- type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(cause.span))
- .ok()?;
- try_extract_error_from_fulfill_cx(
- fulfill_cx,
- infcx,
- placeholder_region,
- error_region,
- )
- },
- )
+ let (ref infcx, key, _) =
+ mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
+ let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
+ type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(cause.span)).ok()?;
+ try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
}
}
@@ -407,7 +375,7 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
#[instrument(skip(fulfill_cx, infcx), level = "debug")]
fn try_extract_error_from_fulfill_cx<'tcx>(
mut fulfill_cx: Box<dyn TraitEngine<'tcx> + 'tcx>,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
@@ -427,7 +395,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
}
fn try_extract_error_from_region_constraints<'tcx>(
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
region_constraints: &RegionConstraintData<'tcx>,
@@ -449,42 +417,38 @@ fn try_extract_error_from_region_constraints<'tcx>(
})?;
debug!(?sub_region, "cause = {:#?}", cause);
- let nice_error = match (error_region, *sub_region) {
- (Some(error_region), ty::ReVar(vid)) => NiceRegionError::new(
- infcx,
- RegionResolutionError::SubSupConflict(
- vid,
- region_var_origin(vid),
- cause.clone(),
- error_region,
- cause.clone(),
- placeholder_region,
- vec![],
- ),
- ),
- (Some(error_region), _) => NiceRegionError::new(
- infcx,
- RegionResolutionError::ConcreteFailure(cause.clone(), error_region, placeholder_region),
+ let error = match (error_region, *sub_region) {
+ (Some(error_region), ty::ReVar(vid)) => RegionResolutionError::SubSupConflict(
+ vid,
+ region_var_origin(vid),
+ cause.clone(),
+ error_region,
+ cause.clone(),
+ placeholder_region,
+ vec![],
),
+ (Some(error_region), _) => {
+ RegionResolutionError::ConcreteFailure(cause.clone(), error_region, placeholder_region)
+ }
// Note universe here is wrong...
- (None, ty::ReVar(vid)) => NiceRegionError::new(
- infcx,
- RegionResolutionError::UpperBoundUniverseConflict(
- vid,
- region_var_origin(vid),
- universe_of_region(vid),
- cause.clone(),
- placeholder_region,
- ),
- ),
- (None, _) => NiceRegionError::new(
- infcx,
- RegionResolutionError::ConcreteFailure(cause.clone(), sub_region, placeholder_region),
+ (None, ty::ReVar(vid)) => RegionResolutionError::UpperBoundUniverseConflict(
+ vid,
+ region_var_origin(vid),
+ universe_of_region(vid),
+ cause.clone(),
+ placeholder_region,
),
+ (None, _) => {
+ RegionResolutionError::ConcreteFailure(cause.clone(), sub_region, placeholder_region)
+ }
};
- nice_error.try_report_from_nll().or_else(|| {
+ NiceRegionError::new(&infcx.err_ctxt(), error).try_report_from_nll().or_else(|| {
if let SubregionOrigin::Subtype(trace) = cause {
- Some(infcx.report_and_explain_type_error(*trace, TypeError::RegionsPlaceholderMismatch))
+ Some(
+ infcx
+ .err_ctxt()
+ .report_and_explain_type_error(*trace, TypeError::RegionsPlaceholderMismatch),
+ )
} else {
None
}
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index f2204c242..583bc2e28 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -16,7 +16,7 @@ use rustc_middle::mir::{
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
};
-use rustc_middle::ty::{self, subst::Subst, suggest_constraining_type_params, PredicateKind, Ty};
+use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty};
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
use rustc_span::def_id::LocalDefId;
use rustc_span::hygiene::DesugaringKind;
@@ -198,7 +198,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
move_span,
move_spans,
*moved_place,
- Some(used_place),
partially_str,
loop_message,
move_msg,
@@ -369,6 +368,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let mut visitor = ConditionVisitor { spans: &spans, name: &name, errors: vec![] };
visitor.visit_body(&body);
+ let mut show_assign_sugg = false;
let isnt_initialized = if let InitializationRequiringAction::PartialAssignment
| InitializationRequiringAction::Assignment = desired_action
{
@@ -396,6 +396,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
.count()
== 0
{
+ show_assign_sugg = true;
"isn't initialized"
} else {
"is possibly-uninitialized"
@@ -446,10 +447,84 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
}
+
err.span_label(decl_span, "binding declared here but left uninitialized");
+ if show_assign_sugg {
+ struct LetVisitor {
+ decl_span: Span,
+ sugg_span: Option<Span>,
+ }
+
+ impl<'v> Visitor<'v> for LetVisitor {
+ fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
+ if self.sugg_span.is_some() {
+ return;
+ }
+ if let hir::StmtKind::Local(hir::Local {
+ span, ty, init: None, ..
+ }) = &ex.kind && span.contains(self.decl_span) {
+ self.sugg_span = ty.map_or(Some(self.decl_span), |ty| Some(ty.span));
+ }
+ hir::intravisit::walk_stmt(self, ex);
+ }
+ }
+
+ let mut visitor = LetVisitor { decl_span, sugg_span: None };
+ visitor.visit_body(&body);
+ if let Some(span) = visitor.sugg_span {
+ self.suggest_assign_value(&mut err, moved_place, span);
+ }
+ }
err
}
+ fn suggest_assign_value(
+ &self,
+ err: &mut Diagnostic,
+ moved_place: PlaceRef<'tcx>,
+ sugg_span: Span,
+ ) {
+ let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
+ debug!("ty: {:?}, kind: {:?}", ty, ty.kind());
+
+ let tcx = self.infcx.tcx;
+ let implements_default = |ty, param_env| {
+ let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
+ return false;
+ };
+ // Regions are already solved, so we must use a fresh InferCtxt,
+ // but the type has region variables, so erase those.
+ tcx.infer_ctxt()
+ .build()
+ .type_implements_trait(
+ default_trait,
+ tcx.erase_regions(ty),
+ ty::List::empty(),
+ param_env,
+ )
+ .must_apply_modulo_regions()
+ };
+
+ let assign_value = match ty.kind() {
+ ty::Bool => "false",
+ ty::Float(_) => "0.0",
+ ty::Int(_) | ty::Uint(_) => "0",
+ ty::Never | ty::Error(_) => "",
+ ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => "vec![]",
+ ty::Adt(_, _) if implements_default(ty, self.param_env) => "Default::default()",
+ _ => "todo!()",
+ };
+
+ if !assign_value.is_empty() {
+ err.span_suggestion_verbose(
+ sugg_span.shrink_to_hi(),
+ format!("consider assigning a value"),
+ format!(" = {}", assign_value),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+
fn suggest_borrow_fn_like(
&self,
err: &mut Diagnostic,
@@ -537,41 +612,40 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
.and_then(|def_id| tcx.hir().get_generics(def_id))
else { return; };
// Try to find predicates on *generic params* that would allow copying `ty`
- let predicates: Result<Vec<_>, _> = tcx.infer_ctxt().enter(|infcx| {
- let mut fulfill_cx = <dyn rustc_infer::traits::TraitEngine<'_>>::new(infcx.tcx);
+ let infcx = tcx.infer_ctxt().build();
+ let mut fulfill_cx = <dyn rustc_infer::traits::TraitEngine<'_>>::new(infcx.tcx);
- let copy_did = infcx.tcx.lang_items().copy_trait().unwrap();
- let cause = ObligationCause::new(
- span,
- self.mir_hir_id(),
- rustc_infer::traits::ObligationCauseCode::MiscObligation,
- );
- fulfill_cx.register_bound(
- &infcx,
- self.param_env,
- // Erase any region vids from the type, which may not be resolved
- infcx.tcx.erase_regions(ty),
- copy_did,
- cause,
- );
- // Select all, including ambiguous predicates
- let errors = fulfill_cx.select_all_or_error(&infcx);
-
- // Only emit suggestion if all required predicates are on generic
- errors
- .into_iter()
- .map(|err| match err.obligation.predicate.kind().skip_binder() {
- PredicateKind::Trait(predicate) => match predicate.self_ty().kind() {
- ty::Param(param_ty) => Ok((
- generics.type_param(param_ty, tcx),
- predicate.trait_ref.print_only_trait_path().to_string(),
- )),
- _ => Err(()),
- },
+ let copy_did = infcx.tcx.lang_items().copy_trait().unwrap();
+ let cause = ObligationCause::new(
+ span,
+ self.mir_hir_id(),
+ rustc_infer::traits::ObligationCauseCode::MiscObligation,
+ );
+ fulfill_cx.register_bound(
+ &infcx,
+ self.param_env,
+ // Erase any region vids from the type, which may not be resolved
+ infcx.tcx.erase_regions(ty),
+ copy_did,
+ cause,
+ );
+ // Select all, including ambiguous predicates
+ let errors = fulfill_cx.select_all_or_error(&infcx);
+
+ // Only emit suggestion if all required predicates are on generic
+ let predicates: Result<Vec<_>, _> = errors
+ .into_iter()
+ .map(|err| match err.obligation.predicate.kind().skip_binder() {
+ PredicateKind::Trait(predicate) => match predicate.self_ty().kind() {
+ ty::Param(param_ty) => Ok((
+ generics.type_param(param_ty, tcx),
+ predicate.trait_ref.print_only_trait_path().to_string(),
+ )),
_ => Err(()),
- })
- .collect()
- });
+ },
+ _ => Err(()),
+ })
+ .collect();
if let Ok(predicates) = predicates {
suggest_constraining_type_params(
@@ -2146,7 +2220,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
StorageDeadOrDrop::Destructor(_) => kind,
},
- ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
+ ProjectionElem::OpaqueCast { .. }
+ | ProjectionElem::Field(..)
+ | ProjectionElem::Downcast(..) => {
match place_ty.ty.kind() {
ty::Adt(def, _) if def.has_dtor(tcx) => {
// Report the outermost adt with a destructor
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 1c01e78ab..582d683dd 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -1,8 +1,5 @@
//! Print diagnostics to explain why values are borrowed.
-use std::collections::VecDeque;
-
-use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Applicability, Diagnostic};
use rustc_index::vec::IndexVec;
use rustc_infer::infer::NllRegionVariableOrigin;
@@ -359,19 +356,37 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let borrow_region_vid = borrow.region;
debug!(?borrow_region_vid);
- let region_sub = self.regioncx.find_sub_region_live_at(borrow_region_vid, location);
+ let mut region_sub = self.regioncx.find_sub_region_live_at(borrow_region_vid, location);
debug!(?region_sub);
- match find_use::find(body, regioncx, tcx, region_sub, location) {
+ let mut use_location = location;
+ let mut use_in_later_iteration_of_loop = false;
+
+ if region_sub == borrow_region_vid {
+ // When `region_sub` is the same as `borrow_region_vid` (the location where the borrow is
+ // issued is the same location that invalidates the reference), this is likely a loop iteration
+ // - in this case, try using the loop terminator location in `find_sub_region_live_at`.
+ if let Some(loop_terminator_location) =
+ regioncx.find_loop_terminator_location(borrow.region, body)
+ {
+ region_sub = self
+ .regioncx
+ .find_sub_region_live_at(borrow_region_vid, loop_terminator_location);
+ debug!("explain_why_borrow_contains_point: region_sub in loop={:?}", region_sub);
+ use_location = loop_terminator_location;
+ use_in_later_iteration_of_loop = true;
+ }
+ }
+
+ match find_use::find(body, regioncx, tcx, region_sub, use_location) {
Some(Cause::LiveVar(local, location)) => {
let span = body.source_info(location).span;
let spans = self
.move_spans(Place::from(local).as_ref(), location)
.or_else(|| self.borrow_spans(span, location));
- let borrow_location = location;
- if self.is_use_in_later_iteration_of_loop(borrow_location, location) {
- let later_use = self.later_use_kind(borrow, spans, location);
+ if use_in_later_iteration_of_loop {
+ let later_use = self.later_use_kind(borrow, spans, use_location);
BorrowExplanation::UsedLaterInLoop(later_use.0, later_use.1, later_use.2)
} else {
// Check if the location represents a `FakeRead`, and adapt the error
@@ -425,131 +440,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
- /// true if `borrow_location` can reach `use_location` by going through a loop and
- /// `use_location` is also inside of that loop
- fn is_use_in_later_iteration_of_loop(
- &self,
- borrow_location: Location,
- use_location: Location,
- ) -> bool {
- let back_edge = self.reach_through_backedge(borrow_location, use_location);
- back_edge.map_or(false, |back_edge| self.can_reach_head_of_loop(use_location, back_edge))
- }
-
- /// Returns the outmost back edge if `from` location can reach `to` location passing through
- /// that back edge
- fn reach_through_backedge(&self, from: Location, to: Location) -> Option<Location> {
- let mut visited_locations = FxHashSet::default();
- let mut pending_locations = VecDeque::new();
- visited_locations.insert(from);
- pending_locations.push_back(from);
- debug!("reach_through_backedge: from={:?} to={:?}", from, to,);
-
- let mut outmost_back_edge = None;
- while let Some(location) = pending_locations.pop_front() {
- debug!(
- "reach_through_backedge: location={:?} outmost_back_edge={:?}
- pending_locations={:?} visited_locations={:?}",
- location, outmost_back_edge, pending_locations, visited_locations
- );
-
- if location == to && outmost_back_edge.is_some() {
- // We've managed to reach the use location
- debug!("reach_through_backedge: found!");
- return outmost_back_edge;
- }
-
- let block = &self.body.basic_blocks[location.block];
-
- if location.statement_index < block.statements.len() {
- let successor = location.successor_within_block();
- if visited_locations.insert(successor) {
- pending_locations.push_back(successor);
- }
- } else {
- pending_locations.extend(
- block
- .terminator()
- .successors()
- .map(|bb| Location { statement_index: 0, block: bb })
- .filter(|s| visited_locations.insert(*s))
- .map(|s| {
- if self.is_back_edge(location, s) {
- match outmost_back_edge {
- None => {
- outmost_back_edge = Some(location);
- }
-
- Some(back_edge)
- if location.dominates(back_edge, &self.dominators) =>
- {
- outmost_back_edge = Some(location);
- }
-
- Some(_) => {}
- }
- }
-
- s
- }),
- );
- }
- }
-
- None
- }
-
- /// true if `from` location can reach `loop_head` location and `loop_head` dominates all the
- /// intermediate nodes
- fn can_reach_head_of_loop(&self, from: Location, loop_head: Location) -> bool {
- self.find_loop_head_dfs(from, loop_head, &mut FxHashSet::default())
- }
-
- fn find_loop_head_dfs(
- &self,
- from: Location,
- loop_head: Location,
- visited_locations: &mut FxHashSet<Location>,
- ) -> bool {
- visited_locations.insert(from);
-
- if from == loop_head {
- return true;
- }
-
- if loop_head.dominates(from, &self.dominators) {
- let block = &self.body.basic_blocks[from.block];
-
- if from.statement_index < block.statements.len() {
- let successor = from.successor_within_block();
-
- if !visited_locations.contains(&successor)
- && self.find_loop_head_dfs(successor, loop_head, visited_locations)
- {
- return true;
- }
- } else {
- for bb in block.terminator().successors() {
- let successor = Location { statement_index: 0, block: bb };
-
- if !visited_locations.contains(&successor)
- && self.find_loop_head_dfs(successor, loop_head, visited_locations)
- {
- return true;
- }
- }
- }
- }
-
- false
- }
-
- /// True if an edge `source -> target` is a backedge -- in other words, if the target
- /// dominates the source.
- fn is_back_edge(&self, source: Location, target: Location) -> bool {
- target.dominates(source, &self.dominators)
- }
-
/// Determine how the borrow was later used.
/// First span returned points to the location of the conflicting use
/// Second span if `Some` is returned in the case of closures and points
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 683084cf0..534d9ecae 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -237,6 +237,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
ProjectionElem::Downcast(..) if opt.including_downcast => return None,
ProjectionElem::Downcast(..) => (),
+ ProjectionElem::OpaqueCast(..) => (),
ProjectionElem::Field(field, _ty) => {
// FIXME(project-rfc_2229#36): print capture precisely here.
if let Some(field) = self.is_upvar_field_projection(PlaceRef {
@@ -317,6 +318,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
PlaceRef { local, projection: proj_base }.ty(self.body, self.infcx.tcx)
}
ProjectionElem::Downcast(..) => place.ty(self.body, self.infcx.tcx),
+ ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(*ty),
ProjectionElem::Field(_, field_type) => PlaceTy::from_ty(*field_type),
},
};
@@ -970,7 +972,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
move_span: Span,
move_spans: UseSpans<'tcx>,
moved_place: Place<'tcx>,
- used_place: Option<PlaceRef<'tcx>>,
partially_str: &str,
loop_message: &str,
move_msg: &str,
@@ -1024,7 +1025,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
let suggest = match self.infcx.tcx.get_diagnostic_item(sym::IntoIterator) {
- Some(def_id) => self.infcx.tcx.infer_ctxt().enter(|infcx| {
+ Some(def_id) => {
+ let infcx = self.infcx.tcx.infer_ctxt().build();
type_known_to_meet_bound_modulo_regions(
&infcx,
self.param_env,
@@ -1035,7 +1037,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
def_id,
DUMMY_SP,
)
- }),
+ }
_ => false,
};
if suggest {
@@ -1058,9 +1060,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
place_name, partially_str, loop_message
),
);
- // If we have a `&mut` ref, we need to reborrow.
- if let Some(ty::Ref(_, _, hir::Mutability::Mut)) = used_place
- .map(|used_place| used_place.ty(self.body, self.infcx.tcx).ty.kind())
+ // If the moved place was a `&mut` ref, then we can
+ // suggest to reborrow it where it was moved, so it
+ // will still be valid by the time we get to the usage.
+ if let ty::Ref(_, _, hir::Mutability::Mut) =
+ moved_place.ty(self.body, self.infcx.tcx).ty.kind()
{
// If we are in a loop this will be suggested later.
if !is_loop_move {
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 8d4c38d3a..5a47f4567 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -401,7 +401,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
};
if let Some(use_spans) = use_spans {
self.explain_captures(
- &mut err, span, span, use_spans, move_place, None, "", "", "", false, true,
+ &mut err, span, span, use_spans, move_place, "", "", "", false, true,
);
}
err
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 6b5014fa9..8ad40c0aa 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -169,6 +169,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
..,
ProjectionElem::Index(_)
| ProjectionElem::ConstantIndex { .. }
+ | ProjectionElem::OpaqueCast { .. }
| ProjectionElem::Subslice { .. }
| ProjectionElem::Downcast(..),
],
@@ -931,7 +932,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let opt_suggestions = self
.infcx
.tcx
- .typeck(path_segment.hir_id.owner)
+ .typeck(path_segment.hir_id.owner.def_id)
.type_dependent_def_id(*hir_id)
.and_then(|def_id| self.infcx.tcx.impl_of_method(def_id))
.map(|def_id| self.infcx.tcx.associated_items(def_id))
@@ -1031,7 +1032,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if look_at_return && hir.get_return_block(closure_id).is_some() {
// ...otherwise we are probably in the tail expression of the function, point at the
// return type.
- match hir.get_by_def_id(hir.get_parent_item(fn_call_id)) {
+ match hir.get_by_def_id(hir.get_parent_item(fn_call_id).def_id) {
hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(sig, ..), .. })
| hir::Node::TraitItem(hir::TraitItem {
ident,
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 34be2874f..15230718d 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -186,7 +186,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if let Some(lower_bound_region) = lower_bound_region {
let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx);
let origin = RelateParamBound(type_test_span, generic_ty, None);
- self.buffer_error(self.infcx.construct_generic_bound_failure(
+ self.buffer_error(self.infcx.err_ctxt().construct_generic_bound_failure(
self.body.source.def_id().expect_local(),
type_test_span,
Some(origin),
@@ -281,7 +281,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let tcx = self.infcx.tcx;
match tcx.hir().get_if_local(def_id) {
Some(Node::ImplItem(impl_item)) => {
- match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id())) {
+ match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id()).def_id)
+ {
Some(Node::Item(Item {
kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
..
@@ -291,7 +292,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
Some(Node::TraitItem(trait_item)) => {
let trait_did = tcx.hir().get_parent_item(trait_item.hir_id());
- match tcx.hir().find_by_def_id(trait_did) {
+ match tcx.hir().find_by_def_id(trait_did.def_id) {
Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => {
// The method being called is defined in the `trait`, but the `'static`
// obligation comes from the `impl`. Find that `impl` so that we can point
@@ -340,7 +341,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
/// Report an error because the universal region `fr` was required to outlive
/// `outlived_fr` but it is not known to do so. For example:
///
- /// ```compile_fail,E0312
+ /// ```compile_fail
/// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
/// ```
///
@@ -364,7 +365,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
// Check if we can use one of the "nice region errors".
if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
- let nice = NiceRegionError::new_from_span(self.infcx, cause.span, o, f);
+ let infer_err = self.infcx.err_ctxt();
+ let nice = NiceRegionError::new_from_span(&infer_err, cause.span, o, f);
if let Some(diag) = nice.try_report_from_nll() {
self.buffer_error(diag);
return;
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 6c1eaa809..c044dbaba 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -251,7 +251,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
.or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr))
.or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr))
.or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr))
- .or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr));
+ .or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr))
+ .or_else(|| self.give_name_if_anonymous_region_appears_in_arg_position_impl_trait(fr));
if let Some(ref value) = value {
self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone());
@@ -707,7 +708,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
hir::AsyncGeneratorKind::Block => " of async block",
hir::AsyncGeneratorKind::Closure => " of async closure",
hir::AsyncGeneratorKind::Fn => {
- let parent_item = hir.get_by_def_id(hir.get_parent_item(mir_hir_id));
+ let parent_item =
+ hir.get_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
let output = &parent_item
.fn_decl()
.expect("generator lowered from async fn should be in fn")
@@ -863,20 +865,13 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
};
let tcx = self.infcx.tcx;
- let body_parent_did = tcx.opt_parent(self.mir_def_id().to_def_id())?;
- if tcx.parent(region.def_id) != body_parent_did
- || tcx.def_kind(body_parent_did) != DefKind::Impl
- {
+ let region_parent = tcx.parent(region.def_id);
+ if tcx.def_kind(region_parent) != DefKind::Impl {
return None;
}
- let mut found = false;
- tcx.fold_regions(tcx.type_of(body_parent_did), |r: ty::Region<'tcx>, _| {
- if *r == ty::ReEarlyBound(region) {
- found = true;
- }
- r
- });
+ let found = tcx
+ .any_free_region_meets(&tcx.type_of(region_parent), |r| *r == ty::ReEarlyBound(region));
Some(RegionName {
name: self.synthesize_region_name(),
@@ -889,4 +884,92 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
),
})
}
+
+ fn give_name_if_anonymous_region_appears_in_arg_position_impl_trait(
+ &self,
+ fr: RegionVid,
+ ) -> Option<RegionName> {
+ let ty::ReEarlyBound(region) = *self.to_error_region(fr)? else {
+ return None;
+ };
+ if region.has_name() {
+ return None;
+ };
+
+ let predicates = self
+ .infcx
+ .tcx
+ .predicates_of(self.body.source.def_id())
+ .instantiate_identity(self.infcx.tcx)
+ .predicates;
+
+ if let Some(upvar_index) = self
+ .regioncx
+ .universal_regions()
+ .defining_ty
+ .upvar_tys()
+ .position(|ty| self.any_param_predicate_mentions(&predicates, ty, region))
+ {
+ let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
+ self.infcx.tcx,
+ &self.upvars,
+ upvar_index,
+ );
+ let region_name = self.synthesize_region_name();
+
+ Some(RegionName {
+ name: region_name,
+ source: RegionNameSource::AnonRegionFromUpvar(upvar_span, upvar_name),
+ })
+ } else if let Some(arg_index) = self
+ .regioncx
+ .universal_regions()
+ .unnormalized_input_tys
+ .iter()
+ .position(|ty| self.any_param_predicate_mentions(&predicates, *ty, region))
+ {
+ let (arg_name, arg_span) = self.regioncx.get_argument_name_and_span_for_region(
+ self.body,
+ &self.local_names,
+ arg_index,
+ );
+ let region_name = self.synthesize_region_name();
+
+ Some(RegionName {
+ name: region_name,
+ source: RegionNameSource::AnonRegionFromArgument(
+ RegionNameHighlight::CannotMatchHirTy(arg_span, arg_name?.to_string()),
+ ),
+ })
+ } else {
+ None
+ }
+ }
+
+ fn any_param_predicate_mentions(
+ &self,
+ predicates: &[ty::Predicate<'tcx>],
+ ty: Ty<'tcx>,
+ region: ty::EarlyBoundRegion,
+ ) -> bool {
+ let tcx = self.infcx.tcx;
+ ty.walk().any(|arg| {
+ if let ty::GenericArgKind::Type(ty) = arg.unpack()
+ && let ty::Param(_) = ty.kind()
+ {
+ predicates.iter().any(|pred| {
+ match pred.kind().skip_binder() {
+ ty::PredicateKind::Trait(data) if data.self_ty() == ty => {}
+ ty::PredicateKind::Projection(data) if data.projection_ty.self_ty() == ty => {}
+ _ => return false,
+ }
+ tcx.any_free_region_meets(pred, |r| {
+ *r == ty::ReEarlyBound(region)
+ })
+ })
+ } else {
+ false
+ }
+ })
+ }
}
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 86da87d06..abfe253d4 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -3,7 +3,6 @@
#![allow(rustc::potential_query_instability)]
#![feature(box_patterns)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(rustc_attrs)]
@@ -132,14 +131,11 @@ fn mir_borrowck<'tcx>(
debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;
- let opt_closure_req = tcx
- .infer_ctxt()
- .with_opaque_type_inference(DefiningAnchor::Bind(hir_owner))
- .enter(|infcx| {
- let input_body: &Body<'_> = &input_body.borrow();
- let promoted: &IndexVec<_, _> = &promoted.borrow();
- do_mir_borrowck(&infcx, input_body, promoted, false).0
- });
+ let infcx =
+ tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build();
+ let input_body: &Body<'_> = &input_body.borrow();
+ let promoted: &IndexVec<_, _> = &promoted.borrow();
+ let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, false).0;
debug!("mir_borrowck done");
tcx.arena.alloc(opt_closure_req)
@@ -151,8 +147,8 @@ fn mir_borrowck<'tcx>(
/// region ids on which the borrow checking was performed together with Polonius
/// facts.
#[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.with_opt_param().as_local().unwrap()), level = "debug")]
-fn do_mir_borrowck<'a, 'tcx>(
- infcx: &InferCtxt<'a, 'tcx>,
+fn do_mir_borrowck<'tcx>(
+ infcx: &InferCtxt<'tcx>,
input_body: &Body<'tcx>,
input_promoted: &IndexVec<Promoted, Body<'tcx>>,
return_body_with_facts: bool,
@@ -475,7 +471,7 @@ pub struct BodyWithBorrowckFacts<'tcx> {
}
struct MirBorrowckCtxt<'cx, 'tcx> {
- infcx: &'cx InferCtxt<'cx, 'tcx>,
+ infcx: &'cx InferCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
body: &'cx Body<'tcx>,
move_data: &'cx MoveData<'tcx>,
@@ -1781,6 +1777,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
for (place_base, elem) in place.iter_projections().rev() {
match elem {
ProjectionElem::Index(_/*operand*/) |
+ ProjectionElem::OpaqueCast(_) |
ProjectionElem::ConstantIndex { .. } |
// assigning to P[i] requires P to be valid.
ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) =>
@@ -2172,6 +2169,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
| ProjectionElem::Index(..)
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. }
+ | ProjectionElem::OpaqueCast { .. }
| ProjectionElem::Downcast(..) => {
let upvar_field_projection = self.is_upvar_field_projection(place);
if let Some(field) = upvar_field_projection {
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 12b2481cc..08fdd28eb 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -55,8 +55,8 @@ pub(crate) struct NllOutput<'tcx> {
/// regions (e.g., region parameters) declared on the function. That set will need to be given to
/// `compute_regions`.
#[instrument(skip(infcx, param_env, body, promoted), level = "debug")]
-pub(crate) fn replace_regions_in_mir<'cx, 'tcx>(
- infcx: &InferCtxt<'cx, 'tcx>,
+pub(crate) fn replace_regions_in_mir<'tcx>(
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &mut Body<'tcx>,
promoted: &mut IndexVec<Promoted, Body<'tcx>>,
@@ -155,7 +155,7 @@ fn populate_polonius_move_facts(
///
/// This may result in errors being reported.
pub(crate) fn compute_regions<'cx, 'tcx>(
- infcx: &InferCtxt<'cx, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
universal_regions: UniversalRegions<'tcx>,
body: &Body<'tcx>,
promoted: &IndexVec<Promoted, Body<'tcx>>,
@@ -318,8 +318,8 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
}
}
-pub(super) fn dump_mir_results<'a, 'tcx>(
- infcx: &InferCtxt<'a, 'tcx>,
+pub(super) fn dump_mir_results<'tcx>(
+ infcx: &InferCtxt<'tcx>,
body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
@@ -368,8 +368,8 @@ pub(super) fn dump_mir_results<'a, 'tcx>(
};
}
-pub(super) fn dump_annotation<'a, 'tcx>(
- infcx: &InferCtxt<'a, 'tcx>,
+pub(super) fn dump_annotation<'tcx>(
+ infcx: &InferCtxt<'tcx>,
body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs
index 6e5a96bee..0e71efd6f 100644
--- a/compiler/rustc_borrowck/src/places_conflict.rs
+++ b/compiler/rustc_borrowck/src/places_conflict.rs
@@ -250,6 +250,7 @@ fn place_components_conflict<'tcx>(
| (ProjectionElem::Index { .. }, _, _)
| (ProjectionElem::ConstantIndex { .. }, _, _)
| (ProjectionElem::Subslice { .. }, _, _)
+ | (ProjectionElem::OpaqueCast { .. }, _, _)
| (ProjectionElem::Downcast { .. }, _, _) => {
// Recursive case. This can still be disjoint on a
// further iteration if this a shallow access and
@@ -317,6 +318,17 @@ fn place_projection_conflict<'tcx>(
debug!("place_element_conflict: DISJOINT-OR-EQ-DEREF");
Overlap::EqualOrDisjoint
}
+ (ProjectionElem::OpaqueCast(v1), ProjectionElem::OpaqueCast(v2)) => {
+ if v1 == v2 {
+ // same type - recur.
+ debug!("place_element_conflict: DISJOINT-OR-EQ-OPAQUE");
+ Overlap::EqualOrDisjoint
+ } else {
+ // Different types. Disjoint!
+ debug!("place_element_conflict: DISJOINT-OPAQUE");
+ Overlap::Disjoint
+ }
+ }
(ProjectionElem::Field(f1, _), ProjectionElem::Field(f2, _)) => {
if f1 == f2 {
// same field (e.g., `a.y` vs. `a.y`) - recur.
@@ -520,6 +532,7 @@ fn place_projection_conflict<'tcx>(
| ProjectionElem::Field(..)
| ProjectionElem::Index(..)
| ProjectionElem::ConstantIndex { .. }
+ | ProjectionElem::OpaqueCast { .. }
| ProjectionElem::Subslice { .. }
| ProjectionElem::Downcast(..),
_,
diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs
index bdf2becb7..2b50cbac9 100644
--- a/compiler/rustc_borrowck/src/prefixes.rs
+++ b/compiler/rustc_borrowck/src/prefixes.rs
@@ -81,6 +81,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
}
ProjectionElem::Downcast(..)
| ProjectionElem::Subslice { .. }
+ | ProjectionElem::OpaqueCast { .. }
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Index(_) => {
cursor = cursor_base;
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 244e6e342..8b63294fb 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -15,7 +15,7 @@ use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound,
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
use rustc_middle::mir::{
Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
- ConstraintCategory, Local, Location, ReturnConstraint,
+ ConstraintCategory, Local, Location, ReturnConstraint, TerminatorKind,
};
use rustc_middle::traits::ObligationCause;
use rustc_middle::traits::ObligationCauseCode;
@@ -565,7 +565,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
#[instrument(skip(self, infcx, body, polonius_output), level = "debug")]
pub(super) fn solve(
&mut self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>,
polonius_output: Option<Rc<PoloniusOutput>>,
@@ -835,7 +835,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// 'a`. See `TypeTest` for more details.
fn check_type_tests(
&self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>,
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
@@ -923,7 +923,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
#[instrument(level = "debug", skip(self, infcx, propagated_outlives_requirements))]
fn try_promote_type_test(
&self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>,
type_test: &TypeTest<'tcx>,
@@ -1036,7 +1036,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
#[instrument(level = "debug", skip(self, infcx))]
fn try_promote_type_test_subject(
&self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
ty: Ty<'tcx>,
) -> Option<ClosureOutlivesSubject<'tcx>> {
let tcx = infcx.tcx;
@@ -1212,7 +1212,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// `point`.
fn eval_verify_bound(
&self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>,
generic_ty: Ty<'tcx>,
@@ -1262,7 +1262,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fn eval_if_eq(
&self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
generic_ty: Ty<'tcx>,
lower_bound: RegionVid,
@@ -1398,7 +1398,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// whether any of the constraints were too strong. In particular,
/// we want to check for a case where a universally quantified
/// region exceeded its bounds. Consider:
- /// ```compile_fail,E0312
+ /// ```compile_fail
/// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
/// ```
/// In this case, returning `x` requires `&'a u32 <: &'b u32`
@@ -1451,7 +1451,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// <https://smallcultfollowing.com/babysteps/blog/2019/01/17/polonius-and-region-errors/>
///
/// In the canonical example
- /// ```compile_fail,E0312
+ /// ```compile_fail
/// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
/// ```
/// returning `x` requires `&'a u32 <: &'b u32` and hence we establish (transitively) a
@@ -1718,7 +1718,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fn check_member_constraints(
&self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
errors_buffer: &mut RegionErrors<'tcx>,
) {
let member_constraints = self.member_constraints.clone();
@@ -2236,6 +2236,27 @@ impl<'tcx> RegionInferenceContext<'tcx> {
pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
self.universe_causes[&universe].clone()
}
+
+ /// Tries to find the terminator of the loop in which the region 'r' resides.
+ /// Returns the location of the terminator if found.
+ pub(crate) fn find_loop_terminator_location(
+ &self,
+ r: RegionVid,
+ body: &Body<'_>,
+ ) -> Option<Location> {
+ let scc = self.constraint_sccs.scc(r.to_region_vid());
+ let locations = self.scc_values.locations_outlived_by(scc);
+ for location in locations {
+ let bb = &body[location.block];
+ if let Some(terminator) = &bb.terminator {
+ // terminator of a loop should be TerminatorKind::FalseUnwind
+ if let TerminatorKind::FalseUnwind { .. } = terminator.kind {
+ return Some(location);
+ }
+ }
+ }
+ None
+ }
}
impl<'tcx> RegionDefinition<'tcx> {
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 9d088642f..465f353aa 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -2,22 +2,18 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::vec_map::VecMap;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::OpaqueTyOrigin;
-use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
use rustc_infer::infer::TyCtxtInferExt as _;
use rustc_infer::infer::{DefiningAnchor, InferCtxt};
use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine};
-use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts};
+use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::{
self, OpaqueHiddenType, OpaqueTypeKey, ToPredicate, Ty, TyCtxt, TypeFoldable,
};
use rustc_span::Span;
-use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::TraitEngineExt as _;
-use crate::session_diagnostics::ConstNotUsedTraitAlias;
-
use super::RegionInferenceContext;
impl<'tcx> RegionInferenceContext<'tcx> {
@@ -63,7 +59,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
#[instrument(level = "debug", skip(self, infcx), ret)]
pub(crate) fn infer_opaque_types(
&self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>,
) -> VecMap<LocalDefId, OpaqueHiddenType<'tcx>> {
let mut result: VecMap<LocalDefId, OpaqueHiddenType<'tcx>> = VecMap::new();
@@ -194,7 +190,7 @@ pub trait InferCtxtExt<'tcx> {
) -> Ty<'tcx>;
}
-impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
+impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
/// Given the fully resolved, instantiated type for an opaque
/// type, i.e., the value of an inference variable like C1 or C2
/// (*), computes the "definition type" for an opaque type
@@ -229,31 +225,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
return self.tcx.ty_error();
}
- let OpaqueTypeKey { def_id, substs } = opaque_type_key;
-
- // Use substs to build up a reverse map from regions to their
- // identity mappings. This is necessary because of `impl
- // Trait` lifetimes are computed by replacing existing
- // lifetimes with 'static and remapping only those used in the
- // `impl Trait` return type, resulting in the parameters
- // shifting.
- let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id.to_def_id());
- debug!(?id_substs);
- let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> =
- substs.iter().enumerate().map(|(index, subst)| (subst, id_substs[index])).collect();
- debug!("map = {:#?}", map);
-
- // Convert the type from the function into a type valid outside
- // the function, by replacing invalid regions with 'static,
- // after producing an error for each of them.
- let definition_ty = instantiated_ty.ty.fold_with(&mut ReverseMapper::new(
- self.tcx,
- opaque_type_key,
- map,
- instantiated_ty.ty,
- instantiated_ty.span,
- ));
- debug!(?definition_ty);
+ let definition_ty = instantiated_ty
+ .remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false, origin)
+ .ty;
if !check_opaque_type_parameter_valid(
self.tcx,
@@ -266,72 +240,70 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// Only check this for TAIT. RPIT already supports `src/test/ui/impl-trait/nested-return-type2.rs`
// on stable and we'd break that.
- if let OpaqueTyOrigin::TyAlias = origin {
- // This logic duplicates most of `check_opaque_meets_bounds`.
- // FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely.
- let param_env = self.tcx.param_env(def_id);
- let body_id = self.tcx.local_def_id_to_hir_id(def_id);
- // HACK This bubble is required for this tests to pass:
- // type-alias-impl-trait/issue-67844-nested-opaque.rs
- self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).enter(
- move |infcx| {
- // Require the hidden type to be well-formed with only the generics of the opaque type.
- // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
- // hidden type is well formed even without those bounds.
- let predicate =
- ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()))
- .to_predicate(infcx.tcx);
- let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
+ let OpaqueTyOrigin::TyAlias = origin else {
+ return definition_ty;
+ };
+ let def_id = opaque_type_key.def_id;
+ // This logic duplicates most of `check_opaque_meets_bounds`.
+ // FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely.
+ let param_env = self.tcx.param_env(def_id);
+ let body_id = self.tcx.local_def_id_to_hir_id(def_id);
+ // HACK This bubble is required for this tests to pass:
+ // type-alias-impl-trait/issue-67844-nested-opaque.rs
+ let infcx =
+ self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
+ // Require the hidden type to be well-formed with only the generics of the opaque type.
+ // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
+ // hidden type is well formed even without those bounds.
+ let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()))
+ .to_predicate(infcx.tcx);
+ let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
- // Require that the hidden type actually fulfills all the bounds of the opaque type, even without
- // the bounds that the function supplies.
- match infcx.register_hidden_type(
- OpaqueTypeKey { def_id, substs: id_substs },
- ObligationCause::misc(instantiated_ty.span, body_id),
- param_env,
+ let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id.to_def_id());
+
+ // Require that the hidden type actually fulfills all the bounds of the opaque type, even without
+ // the bounds that the function supplies.
+ let opaque_ty = self.tcx.mk_opaque(def_id.to_def_id(), id_substs);
+ match infcx
+ .at(&ObligationCause::misc(instantiated_ty.span, body_id), param_env)
+ .eq(opaque_ty, definition_ty)
+ {
+ Ok(infer_ok) => {
+ for obligation in infer_ok.obligations {
+ fulfillment_cx.register_predicate_obligation(&infcx, obligation);
+ }
+ }
+ Err(err) => {
+ infcx
+ .err_ctxt()
+ .report_mismatched_types(
+ &ObligationCause::misc(instantiated_ty.span, body_id),
+ opaque_ty,
definition_ty,
- origin,
- ) {
- Ok(infer_ok) => {
- for obligation in infer_ok.obligations {
- fulfillment_cx.register_predicate_obligation(&infcx, obligation);
- }
- }
- Err(err) => {
- infcx
- .report_mismatched_types(
- &ObligationCause::misc(instantiated_ty.span, body_id),
- self.tcx.mk_opaque(def_id.to_def_id(), id_substs),
- definition_ty,
- err,
- )
- .emit();
- }
- }
+ err,
+ )
+ .emit();
+ }
+ }
- fulfillment_cx.register_predicate_obligation(
- &infcx,
- Obligation::misc(instantiated_ty.span, body_id, param_env, predicate),
- );
+ fulfillment_cx.register_predicate_obligation(
+ &infcx,
+ Obligation::misc(instantiated_ty.span, body_id, param_env, predicate),
+ );
- // Check that all obligations are satisfied by the implementation's
- // version.
- let errors = fulfillment_cx.select_all_or_error(&infcx);
+ // Check that all obligations are satisfied by the implementation's
+ // version.
+ let errors = fulfillment_cx.select_all_or_error(&infcx);
- // This is still required for many(half of the tests in ui/type-alias-impl-trait)
- // tests to pass
- let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
+ // This is still required for many(half of the tests in ui/type-alias-impl-trait)
+ // tests to pass
+ let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
- if errors.is_empty() {
- definition_ty
- } else {
- infcx.report_fulfillment_errors(&errors, None, false);
- self.tcx.ty_error()
- }
- },
- )
- } else {
+ if errors.is_empty() {
definition_ty
+ } else {
+ infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+ self.tcx.ty_error()
}
}
}
@@ -427,221 +399,3 @@ fn check_opaque_type_parameter_valid(
}
true
}
-
-struct ReverseMapper<'tcx> {
- tcx: TyCtxt<'tcx>,
-
- key: ty::OpaqueTypeKey<'tcx>,
- map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
- do_not_error: bool,
-
- /// initially `Some`, set to `None` once error has been reported
- hidden_ty: Option<Ty<'tcx>>,
-
- /// Span of function being checked.
- span: Span,
-}
-
-impl<'tcx> ReverseMapper<'tcx> {
- fn new(
- tcx: TyCtxt<'tcx>,
- key: ty::OpaqueTypeKey<'tcx>,
- map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
- hidden_ty: Ty<'tcx>,
- span: Span,
- ) -> Self {
- Self { tcx, key, map, do_not_error: false, hidden_ty: Some(hidden_ty), span }
- }
-
- fn fold_kind_no_missing_regions_error(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
- assert!(!self.do_not_error);
- self.do_not_error = true;
- let kind = kind.fold_with(self);
- self.do_not_error = false;
- kind
- }
-
- fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
- assert!(!self.do_not_error);
- kind.fold_with(self)
- }
-}
-
-impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
- self.tcx
- }
-
- #[instrument(skip(self), level = "debug")]
- fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
- match *r {
- // Ignore bound regions and `'static` regions that appear in the
- // type, we only need to remap regions that reference lifetimes
- // from the function declaration.
- // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
- ty::ReLateBound(..) | ty::ReStatic => return r,
-
- // If regions have been erased (by writeback), don't try to unerase
- // them.
- ty::ReErased => return r,
-
- // The regions that we expect from borrow checking.
- ty::ReEarlyBound(_) | ty::ReFree(_) => {}
-
- ty::RePlaceholder(_) | ty::ReVar(_) => {
- // All of the regions in the type should either have been
- // erased by writeback, or mapped back to named regions by
- // borrow checking.
- bug!("unexpected region kind in opaque type: {:?}", r);
- }
- }
-
- let generics = self.tcx().generics_of(self.key.def_id);
- match self.map.get(&r.into()).map(|k| k.unpack()) {
- Some(GenericArgKind::Lifetime(r1)) => r1,
- Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
- None if self.do_not_error => self.tcx.lifetimes.re_static,
- None if generics.parent.is_some() => {
- if let Some(hidden_ty) = self.hidden_ty.take() {
- unexpected_hidden_region_diagnostic(
- self.tcx,
- self.tcx.def_span(self.key.def_id),
- hidden_ty,
- r,
- self.key,
- )
- .emit();
- }
- self.tcx.lifetimes.re_static
- }
- None => {
- self.tcx
- .sess
- .struct_span_err(self.span, "non-defining opaque type use in defining scope")
- .span_label(
- self.span,
- format!(
- "lifetime `{}` is part of concrete type but not used in \
- parameter list of the `impl Trait` type alias",
- r
- ),
- )
- .emit();
-
- self.tcx().lifetimes.re_static
- }
- }
- }
-
- fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
- match *ty.kind() {
- ty::Closure(def_id, substs) => {
- // I am a horrible monster and I pray for death. When
- // we encounter a closure here, it is always a closure
- // from within the function that we are currently
- // type-checking -- one that is now being encapsulated
- // in an opaque type. Ideally, we would
- // go through the types/lifetimes that it references
- // and treat them just like we would any other type,
- // which means we would error out if we find any
- // reference to a type/region that is not in the
- // "reverse map".
- //
- // **However,** in the case of closures, there is a
- // somewhat subtle (read: hacky) consideration. The
- // problem is that our closure types currently include
- // all the lifetime parameters declared on the
- // enclosing function, even if they are unused by the
- // closure itself. We can't readily filter them out,
- // so here we replace those values with `'empty`. This
- // can't really make a difference to the rest of the
- // compiler; those regions are ignored for the
- // outlives relation, and hence don't affect trait
- // selection or auto traits, and they are erased
- // during codegen.
-
- let generics = self.tcx.generics_of(def_id);
- let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
- if index < generics.parent_count {
- // Accommodate missing regions in the parent kinds...
- self.fold_kind_no_missing_regions_error(kind)
- } else {
- // ...but not elsewhere.
- self.fold_kind_normally(kind)
- }
- }));
-
- self.tcx.mk_closure(def_id, substs)
- }
-
- ty::Generator(def_id, substs, movability) => {
- let generics = self.tcx.generics_of(def_id);
- let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
- if index < generics.parent_count {
- // Accommodate missing regions in the parent kinds...
- self.fold_kind_no_missing_regions_error(kind)
- } else {
- // ...but not elsewhere.
- self.fold_kind_normally(kind)
- }
- }));
-
- self.tcx.mk_generator(def_id, substs, movability)
- }
-
- ty::Param(param) => {
- // Look it up in the substitution list.
- match self.map.get(&ty.into()).map(|k| k.unpack()) {
- // Found it in the substitution list; replace with the parameter from the
- // opaque type.
- Some(GenericArgKind::Type(t1)) => t1,
- Some(u) => panic!("type mapped to unexpected kind: {:?}", u),
- None => {
- debug!(?param, ?self.map);
- self.tcx
- .sess
- .struct_span_err(
- self.span,
- &format!(
- "type parameter `{}` is part of concrete type but not \
- used in parameter list for the `impl Trait` type alias",
- ty
- ),
- )
- .emit();
-
- self.tcx().ty_error()
- }
- }
- }
-
- _ => ty.super_fold_with(self),
- }
- }
-
- fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
- trace!("checking const {:?}", ct);
- // Find a const parameter
- match ct.kind() {
- ty::ConstKind::Param(..) => {
- // Look it up in the substitution list.
- match self.map.get(&ct.into()).map(|k| k.unpack()) {
- // Found it in the substitution list, replace with the parameter from the
- // opaque type.
- Some(GenericArgKind::Const(c1)) => c1,
- Some(u) => panic!("const mapped to unexpected kind: {:?}", u),
- None => {
- self.tcx.sess.emit_err(ConstNotUsedTraitAlias {
- ct: ct.to_string(),
- span: self.span,
- });
-
- self.tcx().const_error(ct.ty())
- }
- }
- }
-
- _ => ct,
- }
- }
-}
diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs
index 63b2088f7..f30237690 100644
--- a/compiler/rustc_borrowck/src/renumber.rs
+++ b/compiler/rustc_borrowck/src/renumber.rs
@@ -1,8 +1,8 @@
use rustc_index::vec::IndexVec;
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
use rustc_middle::mir::visit::{MutVisitor, TyContext};
+use rustc_middle::mir::Constant;
use rustc_middle::mir::{Body, Location, Promoted};
-use rustc_middle::mir::{Constant, ConstantKind};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
@@ -10,7 +10,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
/// inference variables, returning the number of variables created.
#[instrument(skip(infcx, body, promoted), level = "debug")]
pub fn renumber_mir<'tcx>(
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
body: &mut Body<'tcx>,
promoted: &mut IndexVec<Promoted, Body<'tcx>>,
) {
@@ -28,7 +28,7 @@ pub fn renumber_mir<'tcx>(
/// Replaces all regions appearing in `value` with fresh inference
/// variables.
#[instrument(skip(infcx), level = "debug")]
-pub fn renumber_regions<'tcx, T>(infcx: &InferCtxt<'_, 'tcx>, value: T) -> T
+pub fn renumber_regions<'tcx, T>(infcx: &InferCtxt<'tcx>, value: T) -> T
where
T: TypeFoldable<'tcx>,
{
@@ -38,23 +38,8 @@ where
})
}
-// FIXME(valtrees): This function is necessary because `fold_regions`
-// panics for mir constants in the visitor.
-//
-// Once `visit_mir_constant` is removed we can also remove this function
-// and just use `renumber_regions`.
-fn renumber_regions_in_mir_constant<'tcx>(
- infcx: &InferCtxt<'_, 'tcx>,
- value: ConstantKind<'tcx>,
-) -> ConstantKind<'tcx> {
- infcx.tcx.super_fold_regions(value, |_region, _depth| {
- let origin = NllRegionVariableOrigin::Existential { from_forall: false };
- infcx.next_nll_region_var(origin)
- })
-}
-
struct NllVisitor<'a, 'tcx> {
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
}
impl<'a, 'tcx> NllVisitor<'a, 'tcx> {
@@ -64,13 +49,6 @@ impl<'a, 'tcx> NllVisitor<'a, 'tcx> {
{
renumber_regions(self.infcx, value)
}
-
- fn renumber_regions_in_mir_constant(
- &mut self,
- value: ConstantKind<'tcx>,
- ) -> ConstantKind<'tcx> {
- renumber_regions_in_mir_constant(self.infcx, value)
- }
}
impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> {
@@ -103,7 +81,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> {
#[instrument(skip(self), level = "debug")]
fn visit_constant(&mut self, constant: &mut Constant<'tcx>, _location: Location) {
let literal = constant.literal;
- constant.literal = self.renumber_regions_in_mir_constant(literal);
+ constant.literal = self.renumber_regions(literal);
debug!("constant: {:#?}", constant);
}
}
diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs
index 5d750c6ca..cff3089c3 100644
--- a/compiler/rustc_borrowck/src/session_diagnostics.rs
+++ b/compiler/rustc_borrowck/src/session_diagnostics.rs
@@ -1,12 +1,12 @@
use rustc_errors::{IntoDiagnosticArg, MultiSpan};
-use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic};
+use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::Ty;
use rustc_span::Span;
use crate::diagnostics::RegionName;
-#[derive(SessionDiagnostic)]
-#[diag(borrowck::move_unsized, code = "E0161")]
+#[derive(Diagnostic)]
+#[diag(borrowck_move_unsized, code = "E0161")]
pub(crate) struct MoveUnsized<'tcx> {
pub ty: Ty<'tcx>,
#[primary_span]
@@ -14,8 +14,8 @@ pub(crate) struct MoveUnsized<'tcx> {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(borrowck::higher_ranked_lifetime_error)]
+#[derive(Diagnostic)]
+#[diag(borrowck_higher_ranked_lifetime_error)]
pub(crate) struct HigherRankedLifetimeError {
#[subdiagnostic]
pub cause: Option<HigherRankedErrorCause>,
@@ -23,23 +23,23 @@ pub(crate) struct HigherRankedLifetimeError {
pub span: Span,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub(crate) enum HigherRankedErrorCause {
- #[note(borrowck::could_not_prove)]
+ #[note(borrowck_could_not_prove)]
CouldNotProve { predicate: String },
- #[note(borrowck::could_not_normalize)]
+ #[note(borrowck_could_not_normalize)]
CouldNotNormalize { value: String },
}
-#[derive(SessionDiagnostic)]
-#[diag(borrowck::higher_ranked_subtype_error)]
+#[derive(Diagnostic)]
+#[diag(borrowck_higher_ranked_subtype_error)]
pub(crate) struct HigherRankedSubtypeError {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(borrowck::generic_does_not_live_long_enough)]
+#[derive(Diagnostic)]
+#[diag(borrowck_generic_does_not_live_long_enough)]
pub(crate) struct GenericDoesNotLiveLongEnough {
pub kind: String,
#[primary_span]
@@ -47,24 +47,15 @@ pub(crate) struct GenericDoesNotLiveLongEnough {
}
#[derive(LintDiagnostic)]
-#[diag(borrowck::var_does_not_need_mut)]
+#[diag(borrowck_var_does_not_need_mut)]
pub(crate) struct VarNeedNotMut {
#[suggestion_short(applicability = "machine-applicable", code = "")]
pub span: Span,
}
-
-#[derive(SessionDiagnostic)]
-#[diag(borrowck::const_not_used_in_type_alias)]
-pub(crate) struct ConstNotUsedTraitAlias {
- pub ct: String,
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(borrowck::var_cannot_escape_closure)]
+#[derive(Diagnostic)]
+#[diag(borrowck_var_cannot_escape_closure)]
#[note]
-#[note(borrowck::cannot_escape)]
+#[note(cannot_escape)]
pub(crate) struct FnMutError {
#[primary_span]
pub span: Span,
@@ -72,54 +63,54 @@ pub(crate) struct FnMutError {
pub ty_err: FnMutReturnTypeErr,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub(crate) enum VarHereDenote {
- #[label(borrowck::var_here_captured)]
+ #[label(borrowck_var_here_captured)]
Captured {
#[primary_span]
span: Span,
},
- #[label(borrowck::var_here_defined)]
+ #[label(borrowck_var_here_defined)]
Defined {
#[primary_span]
span: Span,
},
- #[label(borrowck::closure_inferred_mut)]
+ #[label(borrowck_closure_inferred_mut)]
FnMutInferred {
#[primary_span]
span: Span,
},
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub(crate) enum FnMutReturnTypeErr {
- #[label(borrowck::returned_closure_escaped)]
+ #[label(borrowck_returned_closure_escaped)]
ReturnClosure {
#[primary_span]
span: Span,
},
- #[label(borrowck::returned_async_block_escaped)]
+ #[label(borrowck_returned_async_block_escaped)]
ReturnAsyncBlock {
#[primary_span]
span: Span,
},
- #[label(borrowck::returned_ref_escaped)]
+ #[label(borrowck_returned_ref_escaped)]
ReturnRef {
#[primary_span]
span: Span,
},
}
-#[derive(SessionDiagnostic)]
-#[diag(borrowck::lifetime_constraints_error)]
+#[derive(Diagnostic)]
+#[diag(borrowck_lifetime_constraints_error)]
pub(crate) struct LifetimeOutliveErr {
#[primary_span]
pub span: Span,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub(crate) enum LifetimeReturnCategoryErr<'a> {
- #[label(borrowck::returned_lifetime_wrong)]
+ #[label(borrowck_returned_lifetime_wrong)]
WrongReturn {
#[primary_span]
span: Span,
@@ -127,7 +118,7 @@ pub(crate) enum LifetimeReturnCategoryErr<'a> {
outlived_fr_name: RegionName,
fr_name: &'a RegionName,
},
- #[label(borrowck::returned_lifetime_short)]
+ #[label(borrowck_returned_lifetime_short)]
ShortReturn {
#[primary_span]
span: Span,
@@ -149,9 +140,9 @@ impl IntoDiagnosticArg for RegionName {
}
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub(crate) enum RequireStaticErr {
- #[note(borrowck::used_impl_require_static)]
+ #[note(borrowck_used_impl_require_static)]
UsedImpl {
#[primary_span]
multi_span: MultiSpan,
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index 9271a2f4d..a581726a1 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -52,11 +52,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
Some(error_info) => error_info.to_universe_info(old_universe),
None => UniverseInfo::other(),
};
- for u in old_universe..universe {
- self.borrowck_context
- .constraints
- .universe_causes
- .insert(u + 1, universe_info.clone());
+ for u in (old_universe + 1)..=universe {
+ self.borrowck_context.constraints.universe_causes.insert(u, universe_info.clone());
}
}
@@ -71,15 +68,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
where
T: TypeFoldable<'tcx>,
{
+ let old_universe = self.infcx.universe();
+
let (instantiated, _) =
self.infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
- for u in 0..canonical.max_universe.as_u32() {
- let info = UniverseInfo::other();
- self.borrowck_context
- .constraints
- .universe_causes
- .insert(ty::UniverseIndex::from_u32(u), info);
+ for u in (old_universe + 1)..=self.infcx.universe() {
+ self.borrowck_context.constraints.universe_causes.insert(u, UniverseInfo::other());
}
instantiated
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index 71eae0583..d5bfc2f52 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -19,7 +19,7 @@ use crate::{
};
pub(crate) struct ConstraintConversion<'a, 'tcx> {
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
tcx: TyCtxt<'tcx>,
universal_regions: &'a UniversalRegions<'tcx>,
/// Each RBP `GK: 'a` is assumed to be true. These encode
@@ -43,7 +43,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
pub(crate) fn new(
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
universal_regions: &'a UniversalRegions<'tcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
implicit_region_bound: ty::Region<'tcx>,
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index f1b1c33a1..029095926 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -8,7 +8,6 @@ use rustc_infer::infer::InferCtxt;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::traits::query::OutlivesBound;
use rustc_middle::ty::{self, RegionVid, Ty};
-use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
use std::rc::Rc;
use type_op::TypeOpOutput;
@@ -48,7 +47,7 @@ pub(crate) struct CreateResult<'tcx> {
}
pub(crate) fn create<'tcx>(
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
implicit_region_bound: ty::Region<'tcx>,
universal_regions: &Rc<UniversalRegions<'tcx>>,
@@ -197,7 +196,7 @@ impl UniversalRegionRelations<'_> {
}
struct UniversalRegionRelationsBuilder<'this, 'tcx> {
- infcx: &'this InferCtxt<'this, 'tcx>,
+ infcx: &'this InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
universal_regions: Rc<UniversalRegions<'tcx>>,
implicit_region_bound: ty::Region<'tcx>,
@@ -219,6 +218,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
}
pub(crate) fn create(mut self) -> CreateResult<'tcx> {
+ let span = self.infcx.tcx.def_span(self.universal_regions.defining_ty.def_id());
let unnormalized_input_output_tys = self
.universal_regions
.unnormalized_input_tys
@@ -250,7 +250,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
self.infcx
.tcx
.sess
- .delay_span_bug(DUMMY_SP, &format!("failed to normalize {:?}", ty));
+ .delay_span_bug(span, &format!("failed to normalize {:?}", ty));
TypeOpOutput {
output: self.infcx.tcx.ty_error(),
constraints: None,
@@ -301,8 +301,8 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
&self.region_bound_pairs,
self.implicit_region_bound,
self.param_env,
- Locations::All(DUMMY_SP),
- DUMMY_SP,
+ Locations::All(span),
+ span,
ConstraintCategory::Internal,
&mut self.constraints,
)
@@ -362,6 +362,11 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
self.region_bound_pairs
.insert(ty::OutlivesPredicate(GenericKind::Projection(projection_b), r_a));
}
+
+ OutlivesBound::RegionSubOpaque(r_a, def_id, substs) => {
+ self.region_bound_pairs
+ .insert(ty::OutlivesPredicate(GenericKind::Opaque(def_id, substs), r_a));
+ }
}
}
}
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index 4431a2e8e..a66ddd27d 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -7,16 +7,11 @@
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
//! contain revealed `impl Trait` values).
-use crate::type_check::constraint_conversion::ConstraintConversion;
use rustc_index::vec::Idx;
use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_middle::mir::*;
use rustc_middle::ty::Ty;
use rustc_span::Span;
-use rustc_span::DUMMY_SP;
-use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
-use rustc_trait_selection::traits::query::Fallible;
-use type_op::TypeOpOutput;
use crate::universal_regions::UniversalRegions;
@@ -185,7 +180,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
- #[instrument(skip(self, span), level = "debug")]
+ #[instrument(skip(self), level = "debug")]
fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
if let Err(_) =
self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
@@ -194,13 +189,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd
// like to normalize *before* inserting into `local_decls`, but
// doing so ends up causing some other trouble.
- let b = match self.normalize_and_add_constraints(b) {
- Ok(n) => n,
- Err(_) => {
- debug!("equate_inputs_and_outputs: NoSolution");
- b
- }
- };
+ let b = self.normalize(b, Locations::All(span));
// Note: if we have to introduce new placeholders during normalization above, then we won't have
// added those universes to the universe info, which we would want in `relate_tys`.
@@ -218,28 +207,4 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
}
-
- pub(crate) fn normalize_and_add_constraints(&mut self, t: Ty<'tcx>) -> Fallible<Ty<'tcx>> {
- let TypeOpOutput { output: norm_ty, constraints, .. } =
- self.param_env.and(type_op::normalize::Normalize::new(t)).fully_perform(self.infcx)?;
-
- debug!("{:?} normalized to {:?}", t, norm_ty);
-
- for data in constraints {
- ConstraintConversion::new(
- self.infcx,
- &self.borrowck_context.universal_regions,
- &self.region_bound_pairs,
- self.implicit_region_bound,
- self.param_env,
- Locations::All(DUMMY_SP),
- DUMMY_SP,
- ConstraintCategory::Internal,
- &mut self.borrowck_context.constraints,
- )
- .convert_all(&*data);
- }
-
- Ok(norm_ty)
- }
}
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 3713ec3f5..3c1c3ab45 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -123,7 +123,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: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>,
promoted: &IndexVec<Promoted, Body<'tcx>>,
@@ -138,8 +138,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
use_polonius: bool,
) -> MirTypeckResults<'tcx> {
let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
- let mut universe_causes = FxHashMap::default();
- universe_causes.insert(ty::UniverseIndex::from_u32(0), UniverseInfo::other());
let mut constraints = MirTypeckRegionConstraints {
placeholder_indices: PlaceholderIndices::default(),
placeholder_index_to_region: IndexVec::default(),
@@ -148,7 +146,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
member_constraints: MemberConstraintSet::default(),
closure_bounds_mapping: Default::default(),
type_tests: Vec::default(),
- universe_causes,
+ universe_causes: FxHashMap::default(),
};
let CreateResult {
@@ -165,9 +163,8 @@ pub(crate) fn type_check<'mir, 'tcx>(
debug!(?normalized_inputs_and_output);
- for u in ty::UniverseIndex::ROOT..infcx.universe() {
- let info = UniverseInfo::other();
- constraints.universe_causes.insert(u, info);
+ for u in ty::UniverseIndex::ROOT..=infcx.universe() {
+ constraints.universe_causes.insert(u, UniverseInfo::other());
}
let mut borrowck_context = BorrowCheckContext {
@@ -236,7 +233,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
.unwrap();
let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
- if hidden_type.has_infer_types_or_consts() {
+ if hidden_type.has_non_region_infer() {
infcx.tcx.sess.delay_span_bug(
decl.hidden_type.span,
&format!("could not resolve {:#?}", hidden_type.ty.kind()),
@@ -428,12 +425,18 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
}
if let ty::FnDef(def_id, substs) = *constant.literal.ty().kind() {
+ // const_trait_impl: use a non-const param env when checking that a FnDef type is well formed.
+ // this is because the well-formedness of the function does not need to be proved to have `const`
+ // impls for trait bounds.
let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
+ let prev = self.cx.param_env;
+ self.cx.param_env = prev.without_const();
self.cx.normalize_and_prove_instantiated_predicates(
def_id,
instantiated_predicates,
locations,
);
+ self.cx.param_env = prev;
}
}
}
@@ -581,6 +584,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
// modify their locations.
let all_facts = &mut None;
let mut constraints = Default::default();
+ let mut type_tests = Default::default();
let mut closure_bounds = Default::default();
let mut liveness_constraints =
LivenessValues::new(Rc::new(RegionValueElements::new(&promoted_body)));
@@ -592,6 +596,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
&mut this.cx.borrowck_context.constraints.outlives_constraints,
&mut constraints,
);
+ mem::swap(&mut this.cx.borrowck_context.constraints.type_tests, &mut type_tests);
mem::swap(
&mut this.cx.borrowck_context.constraints.closure_bounds_mapping,
&mut closure_bounds,
@@ -616,6 +621,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
swap_constraints(self);
let locations = location.to_locations();
+
+ // Use location of promoted const in collected constraints
+ for type_test in type_tests.iter() {
+ let mut type_test = type_test.clone();
+ type_test.locations = locations;
+ self.cx.borrowck_context.constraints.type_tests.push(type_test)
+ }
for constraint in constraints.outlives().iter() {
let mut constraint = constraint.clone();
constraint.locations = locations;
@@ -764,6 +776,19 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
}
PlaceTy::from_ty(fty)
}
+ ProjectionElem::OpaqueCast(ty) => {
+ let ty = self.sanitize_type(place, ty);
+ let ty = self.cx.normalize(ty, location);
+ self.cx
+ .eq_types(
+ base.ty,
+ ty,
+ location.to_locations(),
+ ConstraintCategory::TypeAnnotation,
+ )
+ .unwrap();
+ PlaceTy::from_ty(ty)
+ }
}
}
@@ -857,7 +882,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 InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
last_span: Span,
body: &'a Body<'tcx>,
@@ -927,7 +952,7 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> {
impl<'tcx> MirTypeckRegionConstraints<'tcx> {
fn placeholder_region(
&mut self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
placeholder: ty::PlaceholderRegion,
) -> ty::Region<'tcx> {
let placeholder_index = self.placeholder_indices.insert(placeholder);
@@ -1011,7 +1036,7 @@ impl Locations {
impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
fn new(
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
body: &'a Body<'tcx>,
param_env: ty::ParamEnv<'tcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
@@ -1170,10 +1195,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
tcx,
self.param_env,
proj,
- |this, field, ()| {
+ |this, field, _| {
let ty = this.field_ty(tcx, field);
self.normalize(ty, locations)
},
+ |_, _| unreachable!(),
);
curr_projected_ty = projected_ty;
}
@@ -1604,7 +1630,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let op_arg_ty = self.normalize(op_arg_ty, term_location);
let category = if from_hir_call {
- ConstraintCategory::CallArgument(func_ty)
+ ConstraintCategory::CallArgument(self.infcx.tcx.erase_regions(func_ty))
} else {
ConstraintCategory::Boring
};
@@ -1757,7 +1783,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// `Sized` bound in no way depends on precise regions, so this
// shouldn't affect `is_sized`.
let erased_ty = tcx.erase_regions(ty);
- if !erased_ty.is_sized(tcx.at(span), self.param_env) {
+ if !erased_ty.is_sized(tcx, self.param_env) {
// in current MIR construction, all non-control-flow rvalue
// expressions evaluate through `as_temp` or `into` a return
// slot or local, so to find all unsized rvalues it is enough
@@ -2189,25 +2215,104 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
}
-
- CastKind::Misc => {
+ CastKind::IntToInt => {
let ty_from = op.ty(body, tcx);
let cast_ty_from = CastTy::from_ty(ty_from);
let cast_ty_to = CastTy::from_ty(*ty);
- // Misc casts are either between floats and ints, or one ptr type to another.
match (cast_ty_from, cast_ty_to) {
- (
- Some(CastTy::Int(_) | CastTy::Float),
- Some(CastTy::Int(_) | CastTy::Float),
- )
- | (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
+ (Some(CastTy::Int(_)), Some(CastTy::Int(_))) => (),
_ => {
span_mirbug!(
self,
rvalue,
- "Invalid Misc cast {:?} -> {:?}",
+ "Invalid IntToInt cast {:?} -> {:?}",
ty_from,
- ty,
+ ty
+ )
+ }
+ }
+ }
+ CastKind::IntToFloat => {
+ let ty_from = op.ty(body, tcx);
+ let cast_ty_from = CastTy::from_ty(ty_from);
+ let cast_ty_to = CastTy::from_ty(*ty);
+ match (cast_ty_from, cast_ty_to) {
+ (Some(CastTy::Int(_)), Some(CastTy::Float)) => (),
+ _ => {
+ span_mirbug!(
+ self,
+ rvalue,
+ "Invalid IntToFloat cast {:?} -> {:?}",
+ ty_from,
+ ty
+ )
+ }
+ }
+ }
+ CastKind::FloatToInt => {
+ let ty_from = op.ty(body, tcx);
+ let cast_ty_from = CastTy::from_ty(ty_from);
+ let cast_ty_to = CastTy::from_ty(*ty);
+ match (cast_ty_from, cast_ty_to) {
+ (Some(CastTy::Float), Some(CastTy::Int(_))) => (),
+ _ => {
+ span_mirbug!(
+ self,
+ rvalue,
+ "Invalid FloatToInt cast {:?} -> {:?}",
+ ty_from,
+ ty
+ )
+ }
+ }
+ }
+ CastKind::FloatToFloat => {
+ let ty_from = op.ty(body, tcx);
+ let cast_ty_from = CastTy::from_ty(ty_from);
+ let cast_ty_to = CastTy::from_ty(*ty);
+ match (cast_ty_from, cast_ty_to) {
+ (Some(CastTy::Float), Some(CastTy::Float)) => (),
+ _ => {
+ span_mirbug!(
+ self,
+ rvalue,
+ "Invalid FloatToFloat cast {:?} -> {:?}",
+ ty_from,
+ ty
+ )
+ }
+ }
+ }
+ CastKind::FnPtrToPtr => {
+ let ty_from = op.ty(body, tcx);
+ let cast_ty_from = CastTy::from_ty(ty_from);
+ let cast_ty_to = CastTy::from_ty(*ty);
+ match (cast_ty_from, cast_ty_to) {
+ (Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
+ _ => {
+ span_mirbug!(
+ self,
+ rvalue,
+ "Invalid FnPtrToPtr cast {:?} -> {:?}",
+ ty_from,
+ ty
+ )
+ }
+ }
+ }
+ CastKind::PtrToPtr => {
+ let ty_from = op.ty(body, tcx);
+ let cast_ty_from = CastTy::from_ty(ty_from);
+ let cast_ty_to = CastTy::from_ty(*ty);
+ match (cast_ty_from, cast_ty_to) {
+ (Some(CastTy::Ptr(_)), Some(CastTy::Ptr(_))) => (),
+ _ => {
+ span_mirbug!(
+ self,
+ rvalue,
+ "Invalid PtrToPtr cast {:?} -> {:?}",
+ ty_from,
+ ty
)
}
}
@@ -2503,6 +2608,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
ProjectionElem::Field(..)
| ProjectionElem::Downcast(..)
+ | ProjectionElem::OpaqueCast(..)
| ProjectionElem::Index(..)
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. } => {
@@ -2723,7 +2829,7 @@ impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
/// constraints in our `InferCtxt`
type ErrorInfo = InstantiateOpaqueType<'tcx>;
- fn fully_perform(mut self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
+ fn fully_perform(mut self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
let (mut output, region_constraints) = scrape_region_constraints(infcx, || {
Ok(InferOk { value: (), obligations: self.obligations.clone() })
})?;
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index c97a6a1a6..4f2dc263b 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -1,6 +1,6 @@
use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
use rustc_infer::infer::NllRegionVariableOrigin;
-use rustc_infer::traits::ObligationCause;
+use rustc_infer::traits::PredicateObligations;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::TypeRelation;
@@ -155,27 +155,16 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
true
}
- fn register_opaque_type(
+ fn register_opaque_type_obligations(
&mut self,
- a: Ty<'tcx>,
- b: Ty<'tcx>,
- a_is_expected: bool,
+ obligations: PredicateObligations<'tcx>,
) -> Result<(), TypeError<'tcx>> {
- let param_env = self.param_env();
- let span = self.span();
- let def_id = self.type_checker.body.source.def_id().expect_local();
- let body_id = self.type_checker.tcx().hir().local_def_id_to_hir_id(def_id);
- let cause = ObligationCause::misc(span, body_id);
self.type_checker
.fully_perform_op(
self.locations,
self.category,
InstantiateOpaqueType {
- obligations: self
- .type_checker
- .infcx
- .handle_opaque_type(a, b, a_is_expected, &cause, param_env)?
- .obligations,
+ obligations,
// These fields are filled in during execution of the operation
base_universe: None,
region_constraints: None,
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 8cf9ed53d..2beb5e0ab 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -22,8 +22,8 @@ use rustc_hir::{BodyOwnerKind, HirId};
use rustc_index::vec::{Idx, IndexVec};
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt};
+use rustc_middle::ty::{InternalSubsts, SubstsRef};
use std::iter;
use crate::nll::ToRegionVid;
@@ -219,7 +219,7 @@ impl<'tcx> UniversalRegions<'tcx> {
/// signature. This will also compute the relationships that are
/// known between those regions.
pub fn new(
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
mir_def: ty::WithOptConstParam<LocalDefId>,
param_env: ty::ParamEnv<'tcx>,
) -> Self {
@@ -382,7 +382,7 @@ impl<'tcx> UniversalRegions<'tcx> {
}
struct UniversalRegionsBuilder<'cx, 'tcx> {
- infcx: &'cx InferCtxt<'cx, 'tcx>,
+ infcx: &'cx InferCtxt<'tcx>,
mir_def: ty::WithOptConstParam<LocalDefId>,
mir_hir_id: HirId,
param_env: ty::ParamEnv<'tcx>,
@@ -414,7 +414,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
- // If this is is a 'root' body (not a closure/generator/inline const), then
+ // If this is a 'root' body (not a closure/generator/inline const), then
// there are no extern regions, so the local regions start at the same
// position as the (empty) sub-list of extern regions
let first_local_index = if self.mir_def.did.to_def_id() == typeck_root_def_id {
@@ -699,7 +699,7 @@ trait InferCtxtExt<'tcx> {
);
}
-impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
+impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
fn replace_free_regions_with_nll_infer_vars<T>(
&self,
origin: NllRegionVariableOrigin,