Auto merge of #138719 - lcnr:concrete_opaque_types-closures, r=oli-obk
merge opaque types defined in nested bodies A small step towards https://github.com/rust-lang/types-team/issues/129 r? `@oli-obk`
This commit is contained in:
commit
db687889a5
19 changed files with 147 additions and 153 deletions
|
@ -73,6 +73,7 @@ mod def_use;
|
||||||
mod diagnostics;
|
mod diagnostics;
|
||||||
mod member_constraints;
|
mod member_constraints;
|
||||||
mod nll;
|
mod nll;
|
||||||
|
mod opaque_types;
|
||||||
mod path_utils;
|
mod path_utils;
|
||||||
mod place_ext;
|
mod place_ext;
|
||||||
mod places_conflict;
|
mod places_conflict;
|
||||||
|
@ -192,7 +193,7 @@ fn do_mir_borrowck<'tcx>(
|
||||||
// Compute non-lexical lifetimes.
|
// Compute non-lexical lifetimes.
|
||||||
let nll::NllOutput {
|
let nll::NllOutput {
|
||||||
regioncx,
|
regioncx,
|
||||||
opaque_type_values,
|
concrete_opaque_types,
|
||||||
polonius_input,
|
polonius_input,
|
||||||
polonius_output,
|
polonius_output,
|
||||||
opt_closure_req,
|
opt_closure_req,
|
||||||
|
@ -222,7 +223,7 @@ fn do_mir_borrowck<'tcx>(
|
||||||
body,
|
body,
|
||||||
®ioncx,
|
®ioncx,
|
||||||
&opt_closure_req,
|
&opt_closure_req,
|
||||||
&opaque_type_values,
|
&concrete_opaque_types,
|
||||||
diags_buffer,
|
diags_buffer,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -357,7 +358,7 @@ fn do_mir_borrowck<'tcx>(
|
||||||
let tainted_by_errors = mbcx.emit_errors();
|
let tainted_by_errors = mbcx.emit_errors();
|
||||||
|
|
||||||
let result = BorrowCheckResult {
|
let result = BorrowCheckResult {
|
||||||
concrete_opaque_types: opaque_type_values,
|
concrete_opaque_types: concrete_opaque_types.into_inner(),
|
||||||
closure_requirements: opt_closure_req,
|
closure_requirements: opt_closure_req,
|
||||||
used_mut_upvars: mbcx.used_mut_upvars,
|
used_mut_upvars: mbcx.used_mut_upvars,
|
||||||
tainted_by_errors,
|
tainted_by_errors,
|
||||||
|
|
|
@ -6,8 +6,6 @@ use std::str::FromStr;
|
||||||
use std::{env, io};
|
use std::{env, io};
|
||||||
|
|
||||||
use polonius_engine::{Algorithm, Output};
|
use polonius_engine::{Algorithm, Output};
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
|
||||||
use rustc_hir::def_id::LocalDefId;
|
|
||||||
use rustc_index::IndexSlice;
|
use rustc_index::IndexSlice;
|
||||||
use rustc_middle::mir::pretty::{PrettyPrintMirOptions, dump_mir_with_options};
|
use rustc_middle::mir::pretty::{PrettyPrintMirOptions, dump_mir_with_options};
|
||||||
use rustc_middle::mir::{
|
use rustc_middle::mir::{
|
||||||
|
@ -15,7 +13,7 @@ use rustc_middle::mir::{
|
||||||
dump_enabled, dump_mir,
|
dump_enabled, dump_mir,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_mir_dataflow::ResultsCursor;
|
use rustc_mir_dataflow::ResultsCursor;
|
||||||
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
||||||
use rustc_mir_dataflow::move_paths::MoveData;
|
use rustc_mir_dataflow::move_paths::MoveData;
|
||||||
|
@ -27,6 +25,7 @@ use tracing::{debug, instrument};
|
||||||
use crate::borrow_set::BorrowSet;
|
use crate::borrow_set::BorrowSet;
|
||||||
use crate::consumers::ConsumerOptions;
|
use crate::consumers::ConsumerOptions;
|
||||||
use crate::diagnostics::{BorrowckDiagnosticsBuffer, RegionErrors};
|
use crate::diagnostics::{BorrowckDiagnosticsBuffer, RegionErrors};
|
||||||
|
use crate::opaque_types::ConcreteOpaqueTypes;
|
||||||
use crate::polonius::PoloniusDiagnosticsContext;
|
use crate::polonius::PoloniusDiagnosticsContext;
|
||||||
use crate::polonius::legacy::{
|
use crate::polonius::legacy::{
|
||||||
PoloniusFacts, PoloniusFactsExt, PoloniusLocationTable, PoloniusOutput,
|
PoloniusFacts, PoloniusFactsExt, PoloniusLocationTable, PoloniusOutput,
|
||||||
|
@ -40,7 +39,7 @@ use crate::{BorrowckInferCtxt, polonius, renumber};
|
||||||
/// closure requirements to propagate, and any generated errors.
|
/// closure requirements to propagate, and any generated errors.
|
||||||
pub(crate) struct NllOutput<'tcx> {
|
pub(crate) struct NllOutput<'tcx> {
|
||||||
pub regioncx: RegionInferenceContext<'tcx>,
|
pub regioncx: RegionInferenceContext<'tcx>,
|
||||||
pub opaque_type_values: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
|
pub concrete_opaque_types: ConcreteOpaqueTypes<'tcx>,
|
||||||
pub polonius_input: Option<Box<PoloniusFacts>>,
|
pub polonius_input: Option<Box<PoloniusFacts>>,
|
||||||
pub polonius_output: Option<Box<PoloniusOutput>>,
|
pub polonius_output: Option<Box<PoloniusOutput>>,
|
||||||
pub opt_closure_req: Option<ClosureRegionRequirements<'tcx>>,
|
pub opt_closure_req: Option<ClosureRegionRequirements<'tcx>>,
|
||||||
|
@ -99,6 +98,8 @@ pub(crate) fn compute_regions<'a, 'tcx>(
|
||||||
|
|
||||||
let location_map = Rc::new(DenseLocationMap::new(body));
|
let location_map = Rc::new(DenseLocationMap::new(body));
|
||||||
|
|
||||||
|
let mut concrete_opaque_types = ConcreteOpaqueTypes::default();
|
||||||
|
|
||||||
// Run the MIR type-checker.
|
// Run the MIR type-checker.
|
||||||
let MirTypeckResults {
|
let MirTypeckResults {
|
||||||
constraints,
|
constraints,
|
||||||
|
@ -116,6 +117,7 @@ pub(crate) fn compute_regions<'a, 'tcx>(
|
||||||
flow_inits,
|
flow_inits,
|
||||||
move_data,
|
move_data,
|
||||||
Rc::clone(&location_map),
|
Rc::clone(&location_map),
|
||||||
|
&mut concrete_opaque_types,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Create the region inference context, taking ownership of the
|
// Create the region inference context, taking ownership of the
|
||||||
|
@ -180,11 +182,11 @@ pub(crate) fn compute_regions<'a, 'tcx>(
|
||||||
infcx.set_tainted_by_errors(guar);
|
infcx.set_tainted_by_errors(guar);
|
||||||
}
|
}
|
||||||
|
|
||||||
let remapped_opaque_tys = regioncx.infer_opaque_types(infcx, opaque_type_values);
|
regioncx.infer_opaque_types(infcx, opaque_type_values, &mut concrete_opaque_types);
|
||||||
|
|
||||||
NllOutput {
|
NllOutput {
|
||||||
regioncx,
|
regioncx,
|
||||||
opaque_type_values: remapped_opaque_tys,
|
concrete_opaque_types,
|
||||||
polonius_input: polonius_facts.map(Box::new),
|
polonius_input: polonius_facts.map(Box::new),
|
||||||
polonius_output,
|
polonius_output,
|
||||||
opt_closure_req: closure_region_requirements,
|
opt_closure_req: closure_region_requirements,
|
||||||
|
@ -300,7 +302,7 @@ pub(super) fn dump_annotation<'tcx, 'infcx>(
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
regioncx: &RegionInferenceContext<'tcx>,
|
regioncx: &RegionInferenceContext<'tcx>,
|
||||||
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
|
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
|
||||||
opaque_type_values: &FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
|
concrete_opaque_types: &ConcreteOpaqueTypes<'tcx>,
|
||||||
diagnostics_buffer: &mut BorrowckDiagnosticsBuffer<'infcx, 'tcx>,
|
diagnostics_buffer: &mut BorrowckDiagnosticsBuffer<'infcx, 'tcx>,
|
||||||
) {
|
) {
|
||||||
let tcx = infcx.tcx;
|
let tcx = infcx.tcx;
|
||||||
|
@ -343,8 +345,8 @@ pub(super) fn dump_annotation<'tcx, 'infcx>(
|
||||||
err
|
err
|
||||||
};
|
};
|
||||||
|
|
||||||
if !opaque_type_values.is_empty() {
|
if !concrete_opaque_types.is_empty() {
|
||||||
err.note(format!("Inferred opaque type values:\n{opaque_type_values:#?}"));
|
err.note(format!("Inferred opaque type values:\n{concrete_opaque_types:#?}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
diagnostics_buffer.buffer_non_error(err);
|
diagnostics_buffer.buffer_non_error(err);
|
||||||
|
|
55
compiler/rustc_borrowck/src/opaque_types.rs
Normal file
55
compiler/rustc_borrowck/src/opaque_types.rs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
|
use rustc_hir::def_id::LocalDefId;
|
||||||
|
use rustc_middle::ty::{OpaqueHiddenType, Ty, TyCtxt};
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub(super) struct ConcreteOpaqueTypes<'tcx> {
|
||||||
|
concrete_opaque_types: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> ConcreteOpaqueTypes<'tcx> {
|
||||||
|
pub(super) fn is_empty(&self) -> bool {
|
||||||
|
self.concrete_opaque_types.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn into_inner(self) -> FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> {
|
||||||
|
self.concrete_opaque_types
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Insert an opaque type into the list of opaque types defined by this function
|
||||||
|
/// after mapping the hidden type to the generic parameters of the opaque type
|
||||||
|
/// definition.
|
||||||
|
pub(super) fn insert(
|
||||||
|
&mut self,
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
def_id: LocalDefId,
|
||||||
|
hidden_ty: OpaqueHiddenType<'tcx>,
|
||||||
|
) {
|
||||||
|
// Sometimes two opaque types are the same only after we remap the generic parameters
|
||||||
|
// back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to
|
||||||
|
// `(X, Y)` and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we
|
||||||
|
// only know that once we convert the generic parameters to those of the opaque type.
|
||||||
|
if let Some(prev) = self.concrete_opaque_types.get_mut(&def_id) {
|
||||||
|
if prev.ty != hidden_ty.ty {
|
||||||
|
let (Ok(guar) | Err(guar)) =
|
||||||
|
prev.build_mismatch_error(&hidden_ty, tcx).map(|d| d.emit());
|
||||||
|
prev.ty = Ty::new_error(tcx, guar);
|
||||||
|
}
|
||||||
|
// Pick a better span if there is one.
|
||||||
|
// FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
|
||||||
|
prev.span = prev.span.substitute_dummy(hidden_ty.span);
|
||||||
|
} else {
|
||||||
|
self.concrete_opaque_types.insert(def_id, hidden_ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn extend_from_nested_body(
|
||||||
|
&mut self,
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
nested_body: &FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
|
||||||
|
) {
|
||||||
|
for (&def_id, &hidden_ty) in nested_body {
|
||||||
|
self.insert(tcx, def_id, hidden_ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ use rustc_trait_selection::traits::ObligationCtxt;
|
||||||
use tracing::{debug, instrument};
|
use tracing::{debug, instrument};
|
||||||
|
|
||||||
use super::RegionInferenceContext;
|
use super::RegionInferenceContext;
|
||||||
|
use crate::opaque_types::ConcreteOpaqueTypes;
|
||||||
use crate::session_diagnostics::{LifetimeMismatchOpaqueParam, NonGenericOpaqueTypeParam};
|
use crate::session_diagnostics::{LifetimeMismatchOpaqueParam, NonGenericOpaqueTypeParam};
|
||||||
use crate::universal_regions::RegionClassification;
|
use crate::universal_regions::RegionClassification;
|
||||||
|
|
||||||
|
@ -67,8 +68,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
&self,
|
&self,
|
||||||
infcx: &InferCtxt<'tcx>,
|
infcx: &InferCtxt<'tcx>,
|
||||||
opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
|
opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
|
||||||
) -> FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> {
|
concrete_opaque_types: &mut ConcreteOpaqueTypes<'tcx>,
|
||||||
let mut result: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> = FxIndexMap::default();
|
) {
|
||||||
let mut decls_modulo_regions: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueTypeKey<'tcx>, Span)> =
|
let mut decls_modulo_regions: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueTypeKey<'tcx>, Span)> =
|
||||||
FxIndexMap::default();
|
FxIndexMap::default();
|
||||||
|
|
||||||
|
@ -143,33 +144,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Sometimes two opaque types are the same only after we remap the generic parameters
|
|
||||||
// back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to
|
|
||||||
// `(X, Y)` and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we
|
|
||||||
// only know that once we convert the generic parameters to those of the opaque type.
|
|
||||||
if let Some(prev) = result.get_mut(&opaque_type_key.def_id) {
|
|
||||||
if prev.ty != ty {
|
|
||||||
let guar = ty.error_reported().err().unwrap_or_else(|| {
|
|
||||||
let (Ok(e) | Err(e)) = prev
|
|
||||||
.build_mismatch_error(
|
|
||||||
&OpaqueHiddenType { ty, span: concrete_type.span },
|
|
||||||
infcx.tcx,
|
|
||||||
)
|
|
||||||
.map(|d| d.emit());
|
|
||||||
e
|
|
||||||
});
|
|
||||||
prev.ty = Ty::new_error(infcx.tcx, guar);
|
|
||||||
}
|
|
||||||
// Pick a better span if there is one.
|
|
||||||
// FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
|
|
||||||
prev.span = prev.span.substitute_dummy(concrete_type.span);
|
|
||||||
} else {
|
|
||||||
result.insert(
|
|
||||||
opaque_type_key.def_id,
|
|
||||||
OpaqueHiddenType { ty, span: concrete_type.span },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
concrete_opaque_types.insert(
|
||||||
|
infcx.tcx,
|
||||||
|
opaque_type_key.def_id,
|
||||||
|
OpaqueHiddenType { ty, span: concrete_type.span },
|
||||||
|
);
|
||||||
// Check that all opaque types have the same region parameters if they have the same
|
// Check that all opaque types have the same region parameters if they have the same
|
||||||
// non-region parameters. This is necessary because within the new solver we perform
|
// non-region parameters. This is necessary because within the new solver we perform
|
||||||
// various query operations modulo regions, and thus could unsoundly select some impls
|
// various query operations modulo regions, and thus could unsoundly select some impls
|
||||||
|
@ -193,7 +173,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Map the regions in the type to named regions. This is similar to what
|
/// Map the regions in the type to named regions. This is similar to what
|
||||||
|
|
|
@ -45,6 +45,7 @@ use crate::borrow_set::BorrowSet;
|
||||||
use crate::constraints::{OutlivesConstraint, OutlivesConstraintSet};
|
use crate::constraints::{OutlivesConstraint, OutlivesConstraintSet};
|
||||||
use crate::diagnostics::UniverseInfo;
|
use crate::diagnostics::UniverseInfo;
|
||||||
use crate::member_constraints::MemberConstraintSet;
|
use crate::member_constraints::MemberConstraintSet;
|
||||||
|
use crate::opaque_types::ConcreteOpaqueTypes;
|
||||||
use crate::polonius::legacy::{PoloniusFacts, PoloniusLocationTable};
|
use crate::polonius::legacy::{PoloniusFacts, PoloniusLocationTable};
|
||||||
use crate::polonius::{PoloniusContext, PoloniusLivenessContext};
|
use crate::polonius::{PoloniusContext, PoloniusLivenessContext};
|
||||||
use crate::region_infer::TypeTest;
|
use crate::region_infer::TypeTest;
|
||||||
|
@ -111,6 +112,7 @@ pub(crate) fn type_check<'a, 'tcx>(
|
||||||
flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
|
flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
|
||||||
move_data: &MoveData<'tcx>,
|
move_data: &MoveData<'tcx>,
|
||||||
location_map: Rc<DenseLocationMap>,
|
location_map: Rc<DenseLocationMap>,
|
||||||
|
concrete_opaque_types: &mut ConcreteOpaqueTypes<'tcx>,
|
||||||
) -> MirTypeckResults<'tcx> {
|
) -> MirTypeckResults<'tcx> {
|
||||||
let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body);
|
let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body);
|
||||||
let mut constraints = MirTypeckRegionConstraints {
|
let mut constraints = MirTypeckRegionConstraints {
|
||||||
|
@ -165,6 +167,7 @@ pub(crate) fn type_check<'a, 'tcx>(
|
||||||
polonius_facts,
|
polonius_facts,
|
||||||
borrow_set,
|
borrow_set,
|
||||||
constraints: &mut constraints,
|
constraints: &mut constraints,
|
||||||
|
concrete_opaque_types,
|
||||||
polonius_liveness,
|
polonius_liveness,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -230,6 +233,7 @@ struct TypeChecker<'a, 'tcx> {
|
||||||
polonius_facts: &'a mut Option<PoloniusFacts>,
|
polonius_facts: &'a mut Option<PoloniusFacts>,
|
||||||
borrow_set: &'a BorrowSet<'tcx>,
|
borrow_set: &'a BorrowSet<'tcx>,
|
||||||
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
|
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
|
||||||
|
concrete_opaque_types: &'a mut ConcreteOpaqueTypes<'tcx>,
|
||||||
/// When using `-Zpolonius=next`, the liveness helper data used to create polonius constraints.
|
/// When using `-Zpolonius=next`, the liveness helper data used to create polonius constraints.
|
||||||
polonius_liveness: Option<PoloniusLivenessContext>,
|
polonius_liveness: Option<PoloniusLivenessContext>,
|
||||||
}
|
}
|
||||||
|
@ -2499,7 +2503,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
args: GenericArgsRef<'tcx>,
|
args: GenericArgsRef<'tcx>,
|
||||||
locations: Locations,
|
locations: Locations,
|
||||||
) -> ty::InstantiatedPredicates<'tcx> {
|
) -> ty::InstantiatedPredicates<'tcx> {
|
||||||
if let Some(closure_requirements) = &tcx.mir_borrowck(def_id).closure_requirements {
|
let closure_borrowck_results = tcx.mir_borrowck(def_id);
|
||||||
|
self.concrete_opaque_types
|
||||||
|
.extend_from_nested_body(tcx, &closure_borrowck_results.concrete_opaque_types);
|
||||||
|
|
||||||
|
if let Some(closure_requirements) = &closure_borrowck_results.closure_requirements {
|
||||||
constraint_conversion::ConstraintConversion::new(
|
constraint_conversion::ConstraintConversion::new(
|
||||||
self.infcx,
|
self.infcx,
|
||||||
self.universal_regions,
|
self.universal_regions,
|
||||||
|
|
|
@ -258,9 +258,6 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
|
||||||
self.tcx
|
self.tcx
|
||||||
}
|
}
|
||||||
fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
|
fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
|
||||||
if let hir::ExprKind::Closure(closure) = ex.kind {
|
|
||||||
self.check(closure.def_id);
|
|
||||||
}
|
|
||||||
intravisit::walk_expr(self, ex);
|
intravisit::walk_expr(self, ex);
|
||||||
}
|
}
|
||||||
fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
|
fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
|
||||||
|
@ -371,14 +368,8 @@ impl RpitConstraintChecker<'_> {
|
||||||
// Use borrowck to get the type with unerased regions.
|
// Use borrowck to get the type with unerased regions.
|
||||||
let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types;
|
let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types;
|
||||||
debug!(?concrete_opaque_types);
|
debug!(?concrete_opaque_types);
|
||||||
for (&def_id, &concrete_type) in concrete_opaque_types {
|
if let Some(&concrete_type) = concrete_opaque_types.get(&self.def_id) {
|
||||||
if def_id != self.def_id {
|
|
||||||
// Ignore constraints for other opaque types.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!(?concrete_type, "found constraint");
|
debug!(?concrete_type, "found constraint");
|
||||||
|
|
||||||
if concrete_type.ty != self.found.ty {
|
if concrete_type.ty != self.found.ty {
|
||||||
if let Ok(d) = self.found.build_mismatch_error(&concrete_type, self.tcx) {
|
if let Ok(d) = self.found.build_mismatch_error(&concrete_type, self.tcx) {
|
||||||
d.emit();
|
d.emit();
|
||||||
|
@ -395,9 +386,6 @@ impl<'tcx> intravisit::Visitor<'tcx> for RpitConstraintChecker<'tcx> {
|
||||||
self.tcx
|
self.tcx
|
||||||
}
|
}
|
||||||
fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
|
fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
|
||||||
if let hir::ExprKind::Closure(closure) = ex.kind {
|
|
||||||
self.check(closure.def_id);
|
|
||||||
}
|
|
||||||
intravisit::walk_expr(self, ex);
|
intravisit::walk_expr(self, ex);
|
||||||
}
|
}
|
||||||
fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
|
fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
//@ known-bug: #122904
|
|
||||||
trait T {}
|
|
||||||
|
|
||||||
type Alias<'a> = impl T;
|
|
||||||
|
|
||||||
struct S;
|
|
||||||
impl<'a> T for &'a S {}
|
|
||||||
|
|
||||||
#[define_opaque(Alias)]
|
|
||||||
fn with_positive(fun: impl Fn(Alias<'_>)) {
|
|
||||||
with_positive(|&n| ());
|
|
||||||
}
|
|
|
@ -2,8 +2,7 @@
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
|
fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
|
||||||
//~^ ERROR cannot resolve opaque type
|
//~^ WARNING elided lifetime has a name
|
||||||
//~| WARNING elided lifetime has a name
|
|
||||||
|x| x
|
|x| x
|
||||||
//~^ ERROR expected generic lifetime parameter, found `'_`
|
//~^ ERROR expected generic lifetime parameter, found `'_`
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,24 +7,14 @@ LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
|
||||||
= note: `#[warn(elided_named_lifetimes)]` on by default
|
= note: `#[warn(elided_named_lifetimes)]` on by default
|
||||||
|
|
||||||
error[E0792]: expected generic lifetime parameter, found `'_`
|
error[E0792]: expected generic lifetime parameter, found `'_`
|
||||||
--> $DIR/impl-fn-predefined-lifetimes.rs:7:9
|
--> $DIR/impl-fn-predefined-lifetimes.rs:6:9
|
||||||
|
|
|
|
||||||
LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
|
LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
|
||||||
| -- this generic parameter must be used with a generic lifetime parameter
|
| -- this generic parameter must be used with a generic lifetime parameter
|
||||||
...
|
LL |
|
||||||
LL | |x| x
|
LL | |x| x
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error[E0720]: cannot resolve opaque type
|
error: aborting due to 1 previous error; 1 warning emitted
|
||||||
--> $DIR/impl-fn-predefined-lifetimes.rs:4:35
|
|
||||||
|
|
|
||||||
LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
|
|
||||||
| ^^^^^^^^^^^^^^^ recursive opaque type
|
|
||||||
...
|
|
||||||
LL | |x| x
|
|
||||||
| ----- returning here with type `{closure@$DIR/impl-fn-predefined-lifetimes.rs:7:5: 7:8}`
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors; 1 warning emitted
|
For more information about this error, try `rustc --explain E0792`.
|
||||||
|
|
||||||
Some errors have detailed explanations: E0720, E0792.
|
|
||||||
For more information about an error, try `rustc --explain E0720`.
|
|
||||||
|
|
|
@ -40,7 +40,6 @@ impl Context {
|
||||||
f: impl FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O>,
|
f: impl FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O>,
|
||||||
) -> TransactionResult<O> {
|
) -> TransactionResult<O> {
|
||||||
//~^ ERROR expected generic lifetime parameter, found `'_`
|
//~^ ERROR expected generic lifetime parameter, found `'_`
|
||||||
//~| ERROR: item does not constrain
|
|
||||||
let mut conn = Connection {};
|
let mut conn = Connection {};
|
||||||
let mut transaction = TestTransaction { conn: &mut conn };
|
let mut transaction = TestTransaction { conn: &mut conn };
|
||||||
f(&mut transaction).await
|
f(&mut transaction).await
|
||||||
|
|
|
@ -24,26 +24,6 @@ note: this opaque type is supposed to be constrained
|
||||||
LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
|
LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: item does not constrain `TransactionFuture::{opaque#0}`
|
|
||||||
--> $DIR/issue-86800.rs:41:31
|
|
||||||
|
|
|
||||||
LL | ) -> TransactionResult<O> {
|
|
||||||
| _______________________________^
|
|
||||||
LL | |
|
|
||||||
LL | |
|
|
||||||
LL | | let mut conn = Connection {};
|
|
||||||
LL | | let mut transaction = TestTransaction { conn: &mut conn };
|
|
||||||
LL | | f(&mut transaction).await
|
|
||||||
LL | | }
|
|
||||||
| |_____^
|
|
||||||
|
|
|
||||||
= note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
|
|
||||||
note: this opaque type is supposed to be constrained
|
|
||||||
--> $DIR/issue-86800.rs:21:34
|
|
||||||
|
|
|
||||||
LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error[E0792]: expected generic lifetime parameter, found `'_`
|
error[E0792]: expected generic lifetime parameter, found `'_`
|
||||||
--> $DIR/issue-86800.rs:31:5
|
--> $DIR/issue-86800.rs:31:5
|
||||||
|
|
|
|
||||||
|
@ -62,13 +42,12 @@ LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionRe
|
||||||
LL | ) -> TransactionResult<O> {
|
LL | ) -> TransactionResult<O> {
|
||||||
| _______________________________^
|
| _______________________________^
|
||||||
LL | |
|
LL | |
|
||||||
LL | |
|
|
||||||
LL | | let mut conn = Connection {};
|
LL | | let mut conn = Connection {};
|
||||||
LL | | let mut transaction = TestTransaction { conn: &mut conn };
|
LL | | let mut transaction = TestTransaction { conn: &mut conn };
|
||||||
LL | | f(&mut transaction).await
|
LL | | f(&mut transaction).await
|
||||||
LL | | }
|
LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0792`.
|
For more information about this error, try `rustc --explain E0792`.
|
||||||
|
|
|
@ -19,22 +19,5 @@ note: this opaque type is supposed to be constrained
|
||||||
LL | type Bar = impl std::fmt::Display;
|
LL | type Bar = impl std::fmt::Display;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: item does not constrain `Bar::{opaque#0}`
|
error: aborting due to 2 previous errors
|
||||||
--> $DIR/const_generic_type.rs:8:31
|
|
||||||
|
|
|
||||||
LL | async fn test<const N: Bar>() {
|
|
||||||
| _______________________________^
|
|
||||||
... |
|
|
||||||
LL | | let x: u32 = N;
|
|
||||||
LL | | }
|
|
||||||
| |_^
|
|
||||||
|
|
|
||||||
= note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
|
|
||||||
note: this opaque type is supposed to be constrained
|
|
||||||
--> $DIR/const_generic_type.rs:5:12
|
|
||||||
|
|
|
||||||
LL | type Bar = impl std::fmt::Display;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ type Bar = impl std::fmt::Display;
|
||||||
async fn test<const N: Bar>() {
|
async fn test<const N: Bar>() {
|
||||||
//~^ ERROR: `Bar` is forbidden as the type of a const generic parameter
|
//~^ ERROR: `Bar` is forbidden as the type of a const generic parameter
|
||||||
//[no_infer]~^^ ERROR item does not constrain
|
//[no_infer]~^^ ERROR item does not constrain
|
||||||
//[no_infer]~| ERROR item does not constrain
|
|
||||||
#[cfg(infer)]
|
#[cfg(infer)]
|
||||||
let x: u32 = N;
|
let x: u32 = N;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
// We previously didn't taint the borrowck result in this test,
|
||||||
|
// causing an ICE later on.
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
trait T {}
|
||||||
|
|
||||||
|
type Alias<'a> = impl T;
|
||||||
|
|
||||||
|
struct S;
|
||||||
|
impl<'a> T for &'a S {}
|
||||||
|
|
||||||
|
#[define_opaque(Alias)]
|
||||||
|
fn with_positive(fun: impl Fn(Alias<'_>)) {
|
||||||
|
//~^ WARN function cannot return without recursing
|
||||||
|
with_positive(|&n| ());
|
||||||
|
//~^ ERROR cannot move out of a shared reference
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,30 @@
|
||||||
|
warning: function cannot return without recursing
|
||||||
|
--> $DIR/error-tainting-issue-122904.rs:12:1
|
||||||
|
|
|
||||||
|
LL | fn with_positive(fun: impl Fn(Alias<'_>)) {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
|
||||||
|
LL |
|
||||||
|
LL | with_positive(|&n| ());
|
||||||
|
| ---------------------- recursive call site
|
||||||
|
|
|
||||||
|
= help: a `loop` may express intention better if this is on purpose
|
||||||
|
= note: `#[warn(unconditional_recursion)]` on by default
|
||||||
|
|
||||||
|
error[E0507]: cannot move out of a shared reference
|
||||||
|
--> $DIR/error-tainting-issue-122904.rs:14:20
|
||||||
|
|
|
||||||
|
LL | with_positive(|&n| ());
|
||||||
|
| ^-
|
||||||
|
| |
|
||||||
|
| data moved here
|
||||||
|
| move occurs because `n` has type `S`, which does not implement the `Copy` trait
|
||||||
|
|
|
||||||
|
help: consider removing the borrow
|
||||||
|
|
|
||||||
|
LL - with_positive(|&n| ());
|
||||||
|
LL + with_positive(|n| ());
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error; 1 warning emitted
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0507`.
|
|
@ -22,7 +22,6 @@ where
|
||||||
for<'any> F: FnMut(&'any mut ()) -> FutNothing<'any>,
|
for<'any> F: FnMut(&'any mut ()) -> FutNothing<'any>,
|
||||||
{
|
{
|
||||||
//~^ ERROR: expected generic lifetime parameter, found `'any`
|
//~^ ERROR: expected generic lifetime parameter, found `'any`
|
||||||
//~| ERROR item does not constrain
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -11,21 +11,6 @@ note: this opaque type is supposed to be constrained
|
||||||
LL | type FutNothing<'a> = impl 'a + Future<Output = ()>;
|
LL | type FutNothing<'a> = impl 'a + Future<Output = ()>;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: item does not constrain `FutNothing::{opaque#0}`
|
|
||||||
--> $DIR/hkl_forbidden4.rs:23:1
|
|
||||||
|
|
|
||||||
LL | / {
|
|
||||||
... |
|
|
||||||
LL | | }
|
|
||||||
| |_^
|
|
||||||
|
|
|
||||||
= note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
|
|
||||||
note: this opaque type is supposed to be constrained
|
|
||||||
--> $DIR/hkl_forbidden4.rs:10:23
|
|
||||||
|
|
|
||||||
LL | type FutNothing<'a> = impl 'a + Future<Output = ()>;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: concrete type differs from previous defining opaque type use
|
error: concrete type differs from previous defining opaque type use
|
||||||
--> $DIR/hkl_forbidden4.rs:12:1
|
--> $DIR/hkl_forbidden4.rs:12:1
|
||||||
|
|
|
|
||||||
|
@ -54,10 +39,10 @@ LL | type FutNothing<'a> = impl 'a + Future<Output = ()>;
|
||||||
| -- this generic parameter must be used with a generic lifetime parameter
|
| -- this generic parameter must be used with a generic lifetime parameter
|
||||||
...
|
...
|
||||||
LL | / {
|
LL | / {
|
||||||
... |
|
LL | |
|
||||||
LL | | }
|
LL | | }
|
||||||
| |_^
|
| |_^
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0792`.
|
For more information about this error, try `rustc --explain E0792`.
|
||||||
|
|
|
@ -6,7 +6,7 @@ trait Foo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Foo for () {
|
impl Foo for () {
|
||||||
type Assoc<'a> = impl Sized; //~ ERROR unconstrained opaque type
|
type Assoc<'a> = impl Sized;
|
||||||
fn bar<'a: 'a>()
|
fn bar<'a: 'a>()
|
||||||
where
|
where
|
||||||
Self::Assoc<'a>:,
|
Self::Assoc<'a>:,
|
||||||
|
|
|
@ -9,14 +9,6 @@ LL | fn bar<'a: 'a>()
|
||||||
LL | let _: Self::Assoc<'a> = x;
|
LL | let _: Self::Assoc<'a> = x;
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: unconstrained opaque type
|
error: aborting due to 1 previous error
|
||||||
--> $DIR/in-assoc-ty-early-bound2.rs:9:22
|
|
||||||
|
|
|
||||||
LL | type Assoc<'a> = impl Sized;
|
|
||||||
| ^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: `Assoc` must be used in combination with a concrete type within the same impl
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0700`.
|
For more information about this error, try `rustc --explain E0700`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue