Auto merge of #87587 - oli-obk:lazy_tait, r=spastorino
Various refactorings of the TAIT infrastructure Before this PR we used to store the opaque type knowledge outside the `InferCtxt`, so it got recomputed on every opaque type instantiation. I also removed a feature gate check that makes no sense in the planned lazy TAIT resolution scheme Each commit passes all tests, so this PR is best reviewed commit by commit. r? `@spastorino`
This commit is contained in:
commit
d488de82f3
33 changed files with 338 additions and 481 deletions
|
@ -4,10 +4,12 @@ pub use self::RegionVariableOrigin::*;
|
|||
pub use self::SubregionOrigin::*;
|
||||
pub use self::ValuePairs::*;
|
||||
|
||||
use self::opaque_types::OpaqueTypeMap;
|
||||
pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog};
|
||||
|
||||
use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine};
|
||||
|
||||
use hir::def_id::CRATE_DEF_ID;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::undo_log::Rollback;
|
||||
|
@ -59,6 +61,7 @@ pub mod lattice;
|
|||
mod lexical_region_resolve;
|
||||
mod lub;
|
||||
pub mod nll_relate;
|
||||
pub mod opaque_types;
|
||||
pub mod outlives;
|
||||
pub mod region_constraints;
|
||||
pub mod resolve;
|
||||
|
@ -191,6 +194,19 @@ pub struct InferCtxtInner<'tcx> {
|
|||
region_obligations: Vec<(hir::HirId, RegionObligation<'tcx>)>,
|
||||
|
||||
undo_log: InferCtxtUndoLogs<'tcx>,
|
||||
|
||||
// Opaque types found in explicit return types and their
|
||||
// associated fresh inference variable. Writeback resolves these
|
||||
// variables to get the concrete type, which can be used to
|
||||
// 'de-opaque' OpaqueTypeDecl, after typeck is done with all functions.
|
||||
pub opaque_types: OpaqueTypeMap<'tcx>,
|
||||
|
||||
/// A map from inference variables created from opaque
|
||||
/// type instantiations (`ty::Infer`) to the actual opaque
|
||||
/// type (`ty::Opaque`). Used during fallback to map unconstrained
|
||||
/// opaque type inference variables to their corresponding
|
||||
/// opaque type.
|
||||
pub opaque_types_vars: FxHashMap<Ty<'tcx>, Ty<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> InferCtxtInner<'tcx> {
|
||||
|
@ -204,6 +220,8 @@ impl<'tcx> InferCtxtInner<'tcx> {
|
|||
float_unification_storage: ut::UnificationTableStorage::new(),
|
||||
region_constraint_storage: Some(RegionConstraintStorage::new()),
|
||||
region_obligations: vec![],
|
||||
opaque_types: Default::default(),
|
||||
opaque_types_vars: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -273,6 +291,10 @@ impl<'tcx> InferCtxtInner<'tcx> {
|
|||
pub struct InferCtxt<'a, 'tcx> {
|
||||
pub tcx: TyCtxt<'tcx>,
|
||||
|
||||
/// The `DefId` of the item in whose context we are performing inference or typeck.
|
||||
/// It is used to check whether an opaque type use is a defining use.
|
||||
pub defining_use_anchor: LocalDefId,
|
||||
|
||||
/// During type-checking/inference of a body, `in_progress_typeck_results`
|
||||
/// contains a reference to the typeck results being built up, which are
|
||||
/// used for reading closure kinds/signatures as they are inferred,
|
||||
|
@ -531,6 +553,7 @@ impl<'tcx> fmt::Display for FixupError<'tcx> {
|
|||
pub struct InferCtxtBuilder<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
fresh_typeck_results: Option<RefCell<ty::TypeckResults<'tcx>>>,
|
||||
defining_use_anchor: LocalDefId,
|
||||
}
|
||||
|
||||
pub trait TyCtxtInferExt<'tcx> {
|
||||
|
@ -539,15 +562,31 @@ pub trait TyCtxtInferExt<'tcx> {
|
|||
|
||||
impl TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
|
||||
fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> {
|
||||
InferCtxtBuilder { tcx: self, fresh_typeck_results: None }
|
||||
InferCtxtBuilder {
|
||||
tcx: self,
|
||||
defining_use_anchor: CRATE_DEF_ID,
|
||||
fresh_typeck_results: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> InferCtxtBuilder<'tcx> {
|
||||
/// Used only by `rustc_typeck` during body type-checking/inference,
|
||||
/// will initialize `in_progress_typeck_results` with fresh `TypeckResults`.
|
||||
/// Will also change the scope for opaque type defining use checks to the given owner.
|
||||
pub fn with_fresh_in_progress_typeck_results(mut self, table_owner: LocalDefId) -> Self {
|
||||
self.fresh_typeck_results = Some(RefCell::new(ty::TypeckResults::new(table_owner)));
|
||||
self.with_opaque_type_inference(table_owner)
|
||||
}
|
||||
|
||||
/// Whenever the `InferCtxt` should be able to handle defining uses of opaque types,
|
||||
/// you need to call this function. Otherwise the opaque type will be treated opaquely.
|
||||
///
|
||||
/// It is only meant to be called in two places, for typeck
|
||||
/// (via `with_fresh_in_progress_typeck_results`) and for the inference context used
|
||||
/// in mir borrowck.
|
||||
pub fn with_opaque_type_inference(mut self, defining_use_anchor: LocalDefId) -> Self {
|
||||
self.defining_use_anchor = defining_use_anchor;
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -575,10 +614,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
|||
}
|
||||
|
||||
pub fn enter<R>(&mut self, f: impl for<'a> FnOnce(InferCtxt<'a, 'tcx>) -> R) -> R {
|
||||
let InferCtxtBuilder { tcx, ref fresh_typeck_results } = *self;
|
||||
let InferCtxtBuilder { tcx, defining_use_anchor, ref fresh_typeck_results } = *self;
|
||||
let in_progress_typeck_results = fresh_typeck_results.as_ref();
|
||||
f(InferCtxt {
|
||||
tcx,
|
||||
defining_use_anchor,
|
||||
in_progress_typeck_results,
|
||||
inner: RefCell::new(InferCtxtInner::new()),
|
||||
lexical_region_resolutions: RefCell::new(None),
|
||||
|
|
47
compiler/rustc_infer/src/infer/opaque_types.rs
Normal file
47
compiler/rustc_infer/src/infer/opaque_types.rs
Normal file
|
@ -0,0 +1,47 @@
|
|||
use rustc_data_structures::vec_map::VecMap;
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::ty::{OpaqueTypeKey, Ty};
|
||||
use rustc_span::Span;
|
||||
|
||||
pub type OpaqueTypeMap<'tcx> = VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>;
|
||||
|
||||
/// Information about the opaque types whose values we
|
||||
/// are inferring in this function (these are the `impl Trait` that
|
||||
/// appear in the return type).
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct OpaqueTypeDecl<'tcx> {
|
||||
/// The opaque type (`ty::Opaque`) for this declaration.
|
||||
pub opaque_type: Ty<'tcx>,
|
||||
|
||||
/// The span of this particular definition of the opaque type. So
|
||||
/// for example:
|
||||
///
|
||||
/// ```ignore (incomplete snippet)
|
||||
/// type Foo = impl Baz;
|
||||
/// fn bar() -> Foo {
|
||||
/// // ^^^ This is the span we are looking for!
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// In cases where the fn returns `(impl Trait, impl Trait)` or
|
||||
/// other such combinations, the result is currently
|
||||
/// over-approximated, but better than nothing.
|
||||
pub definition_span: Span,
|
||||
|
||||
/// The type variable that represents the value of the opaque type
|
||||
/// that we require. In other words, after we compile this function,
|
||||
/// we will be created a constraint like:
|
||||
///
|
||||
/// Foo<'a, T> = ?C
|
||||
///
|
||||
/// where `?C` is the value of this type variable. =) It may
|
||||
/// naturally refer to the type and lifetime parameters in scope
|
||||
/// in this function, though ultimately it should only reference
|
||||
/// those that are arguments to `Foo` in the constraint above. (In
|
||||
/// other words, `?C` should not include `'b`, even though it's a
|
||||
/// lifetime parameter on `foo`.)
|
||||
pub concrete_ty: Ty<'tcx>,
|
||||
|
||||
/// The origin of the opaque type.
|
||||
pub origin: hir::OpaqueTyOrigin,
|
||||
}
|
|
@ -105,7 +105,7 @@ fn mir_borrowck<'tcx>(
|
|||
let (input_body, promoted) = tcx.mir_promoted(def);
|
||||
debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
|
||||
|
||||
let opt_closure_req = tcx.infer_ctxt().enter(|infcx| {
|
||||
let opt_closure_req = tcx.infer_ctxt().with_opaque_type_inference(def.did).enter(|infcx| {
|
||||
let input_body: &Body<'_> = &input_body.borrow();
|
||||
let promoted: &IndexVec<_, _> = &promoted.borrow();
|
||||
do_mir_borrowck(&infcx, input_body, promoted)
|
||||
|
|
|
@ -179,21 +179,20 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
|||
liveness::generate(&mut cx, body, elements, flow_inits, move_data, location_table);
|
||||
|
||||
translate_outlives_facts(&mut cx);
|
||||
let mut opaque_type_values = cx.opaque_type_values;
|
||||
let opaque_type_values = mem::take(&mut infcx.inner.borrow_mut().opaque_types);
|
||||
|
||||
for (_, revealed_ty) in &mut opaque_type_values {
|
||||
*revealed_ty = infcx.resolve_vars_if_possible(*revealed_ty);
|
||||
opaque_type_values
|
||||
.into_iter()
|
||||
.filter_map(|(opaque_type_key, decl)| {
|
||||
let mut revealed_ty = infcx.resolve_vars_if_possible(decl.concrete_ty);
|
||||
if revealed_ty.has_infer_types_or_consts() {
|
||||
infcx.tcx.sess.delay_span_bug(
|
||||
body.span,
|
||||
&format!("could not resolve {:#?}", revealed_ty.kind()),
|
||||
);
|
||||
*revealed_ty = infcx.tcx.ty_error();
|
||||
revealed_ty = infcx.tcx.ty_error();
|
||||
}
|
||||
}
|
||||
|
||||
opaque_type_values.retain(|(opaque_type_key, resolved_ty)| {
|
||||
let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind() {
|
||||
let concrete_is_opaque = if let ty::Opaque(def_id, _) = revealed_ty.kind() {
|
||||
*def_id == opaque_type_key.def_id
|
||||
} else {
|
||||
false
|
||||
|
@ -223,10 +222,12 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
|||
"eq_opaque_type_and_type: non-defining use of {:?}",
|
||||
opaque_type_key.def_id,
|
||||
);
|
||||
None
|
||||
} else {
|
||||
Some((opaque_type_key, revealed_ty))
|
||||
}
|
||||
!concrete_is_opaque
|
||||
});
|
||||
opaque_type_values
|
||||
})
|
||||
.collect()
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -865,7 +866,6 @@ struct TypeChecker<'a, 'tcx> {
|
|||
reported_errors: FxHashSet<(Ty<'tcx>, Span)>,
|
||||
borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
|
||||
universal_region_relations: &'a UniversalRegionRelations<'tcx>,
|
||||
opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
|
||||
}
|
||||
|
||||
struct BorrowCheckContext<'a, 'tcx> {
|
||||
|
@ -1025,7 +1025,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
borrowck_context,
|
||||
reported_errors: Default::default(),
|
||||
universal_region_relations,
|
||||
opaque_type_values: VecMap::default(),
|
||||
};
|
||||
checker.check_user_type_annotations();
|
||||
checker
|
||||
|
@ -1289,10 +1288,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
let body = self.body;
|
||||
let mir_def_id = body.source.def_id().expect_local();
|
||||
|
||||
let mut opaque_type_values = VecMap::new();
|
||||
|
||||
debug!("eq_opaque_type_and_type: mir_def_id={:?}", mir_def_id);
|
||||
let opaque_type_map = self.fully_perform_op(
|
||||
self.fully_perform_op(
|
||||
locations,
|
||||
category,
|
||||
CustomTypeOp::new(
|
||||
|
@ -1307,9 +1304,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
// to `Box<?T>`, returning an `opaque_type_map` mapping `{Foo<T> -> ?T}`.
|
||||
// (Note that the key of the map is both the def-id of `Foo` along with
|
||||
// any generic parameters.)
|
||||
let (output_ty, opaque_type_map) =
|
||||
obligations.add(infcx.instantiate_opaque_types(
|
||||
mir_def_id,
|
||||
let output_ty = obligations.add(infcx.instantiate_opaque_types(
|
||||
dummy_body_id,
|
||||
param_env,
|
||||
anon_ty,
|
||||
|
@ -1318,9 +1313,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
debug!(
|
||||
"eq_opaque_type_and_type: \
|
||||
instantiated output_ty={:?} \
|
||||
opaque_type_map={:#?} \
|
||||
revealed_ty={:?}",
|
||||
output_ty, opaque_type_map, revealed_ty
|
||||
output_ty, revealed_ty
|
||||
);
|
||||
|
||||
// Make sure that the inferred types are well-formed. I'm
|
||||
|
@ -1338,30 +1332,21 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
.eq(output_ty, revealed_ty)?,
|
||||
);
|
||||
|
||||
for &(opaque_type_key, opaque_decl) in &opaque_type_map {
|
||||
opaque_type_values.insert(opaque_type_key, opaque_decl.concrete_ty);
|
||||
}
|
||||
|
||||
debug!("eq_opaque_type_and_type: equated");
|
||||
|
||||
Ok(InferOk {
|
||||
value: Some(opaque_type_map),
|
||||
obligations: obligations.into_vec(),
|
||||
})
|
||||
Ok(InferOk { value: (), obligations: obligations.into_vec() })
|
||||
},
|
||||
|| "input_output".to_string(),
|
||||
),
|
||||
)?;
|
||||
|
||||
self.opaque_type_values.extend(opaque_type_values);
|
||||
|
||||
let universal_region_relations = self.universal_region_relations;
|
||||
|
||||
// Finally, if we instantiated the anon types successfully, we
|
||||
// have to solve any bounds (e.g., `-> impl Iterator` needs to
|
||||
// prove that `T: Iterator` where `T` is the type we
|
||||
// instantiated it with).
|
||||
if let Some(opaque_type_map) = opaque_type_map {
|
||||
let opaque_type_map = self.infcx.inner.borrow().opaque_types.clone();
|
||||
for (opaque_type_key, opaque_decl) in opaque_type_map {
|
||||
self.fully_perform_op(
|
||||
locations,
|
||||
|
@ -1380,7 +1365,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -2,11 +2,11 @@ use crate::infer::InferCtxtExt as _;
|
|||
use crate::traits::{self, ObligationCause, PredicateObligation};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::vec_map::VecMap;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
|
||||
use rustc_infer::infer::free_regions::FreeRegionRelations;
|
||||
use rustc_infer::infer::opaque_types::OpaqueTypeDecl;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::{self, InferCtxt, InferOk};
|
||||
use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor};
|
||||
|
@ -16,72 +16,6 @@ use rustc_span::Span;
|
|||
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
pub type OpaqueTypeMap<'tcx> = VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>;
|
||||
|
||||
/// Information about the opaque types whose values we
|
||||
/// are inferring in this function (these are the `impl Trait` that
|
||||
/// appear in the return type).
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct OpaqueTypeDecl<'tcx> {
|
||||
/// The opaque type (`ty::Opaque`) for this declaration.
|
||||
pub opaque_type: Ty<'tcx>,
|
||||
|
||||
/// The span of this particular definition of the opaque type. So
|
||||
/// for example:
|
||||
///
|
||||
/// ```ignore (incomplete snippet)
|
||||
/// type Foo = impl Baz;
|
||||
/// fn bar() -> Foo {
|
||||
/// // ^^^ This is the span we are looking for!
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// In cases where the fn returns `(impl Trait, impl Trait)` or
|
||||
/// other such combinations, the result is currently
|
||||
/// over-approximated, but better than nothing.
|
||||
pub definition_span: Span,
|
||||
|
||||
/// The type variable that represents the value of the opaque type
|
||||
/// that we require. In other words, after we compile this function,
|
||||
/// we will be created a constraint like:
|
||||
///
|
||||
/// Foo<'a, T> = ?C
|
||||
///
|
||||
/// where `?C` is the value of this type variable. =) It may
|
||||
/// naturally refer to the type and lifetime parameters in scope
|
||||
/// in this function, though ultimately it should only reference
|
||||
/// those that are arguments to `Foo` in the constraint above. (In
|
||||
/// other words, `?C` should not include `'b`, even though it's a
|
||||
/// lifetime parameter on `foo`.)
|
||||
pub concrete_ty: Ty<'tcx>,
|
||||
|
||||
/// Returns `true` if the `impl Trait` bounds include region bounds.
|
||||
/// For example, this would be true for:
|
||||
///
|
||||
/// fn foo<'a, 'b, 'c>() -> impl Trait<'c> + 'a + 'b
|
||||
///
|
||||
/// but false for:
|
||||
///
|
||||
/// fn foo<'c>() -> impl Trait<'c>
|
||||
///
|
||||
/// unless `Trait` was declared like:
|
||||
///
|
||||
/// trait Trait<'c>: 'c
|
||||
///
|
||||
/// in which case it would be true.
|
||||
///
|
||||
/// This is used during regionck to decide whether we need to
|
||||
/// impose any additional constraints to ensure that region
|
||||
/// variables in `concrete_ty` wind up being constrained to
|
||||
/// something from `substs` (or, at minimum, things that outlive
|
||||
/// the fn body). (Ultimately, writeback is responsible for this
|
||||
/// check.)
|
||||
pub has_required_region_bounds: bool,
|
||||
|
||||
/// The origin of the opaque type.
|
||||
pub origin: hir::OpaqueTyOrigin,
|
||||
}
|
||||
|
||||
/// Whether member constraints should be generated for all opaque types
|
||||
#[derive(Debug)]
|
||||
pub enum GenerateMemberConstraints {
|
||||
|
@ -98,18 +32,13 @@ pub enum GenerateMemberConstraints {
|
|||
pub trait InferCtxtExt<'tcx> {
|
||||
fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
|
||||
&self,
|
||||
parent_def_id: LocalDefId,
|
||||
body_id: hir::HirId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
value: T,
|
||||
value_span: Span,
|
||||
) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)>;
|
||||
) -> InferOk<'tcx, T>;
|
||||
|
||||
fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>(
|
||||
&self,
|
||||
opaque_types: &OpaqueTypeMap<'tcx>,
|
||||
free_region_relations: &FRR,
|
||||
);
|
||||
fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>(&self, free_region_relations: &FRR);
|
||||
|
||||
fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
|
||||
&self,
|
||||
|
@ -164,28 +93,20 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
/// - `value_span` -- the span where the value came from, used in error reporting
|
||||
fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
|
||||
&self,
|
||||
parent_def_id: LocalDefId,
|
||||
body_id: hir::HirId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
value: T,
|
||||
value_span: Span,
|
||||
) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)> {
|
||||
) -> InferOk<'tcx, T> {
|
||||
debug!(
|
||||
"instantiate_opaque_types(value={:?}, parent_def_id={:?}, body_id={:?}, \
|
||||
"instantiate_opaque_types(value={:?}, body_id={:?}, \
|
||||
param_env={:?}, value_span={:?})",
|
||||
value, parent_def_id, body_id, param_env, value_span,
|
||||
value, body_id, param_env, value_span,
|
||||
);
|
||||
let mut instantiator = Instantiator {
|
||||
infcx: self,
|
||||
parent_def_id,
|
||||
body_id,
|
||||
param_env,
|
||||
value_span,
|
||||
opaque_types: Default::default(),
|
||||
obligations: vec![],
|
||||
};
|
||||
let mut instantiator =
|
||||
Instantiator { infcx: self, body_id, param_env, value_span, obligations: vec![] };
|
||||
let value = instantiator.instantiate_opaque_types_in_map(value);
|
||||
InferOk { value: (value, instantiator.opaque_types), obligations: instantiator.obligations }
|
||||
InferOk { value, obligations: instantiator.obligations }
|
||||
}
|
||||
|
||||
/// Given the map `opaque_types` containing the opaque
|
||||
|
@ -350,12 +271,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
/// - `opaque_types` -- the map produced by `instantiate_opaque_types`
|
||||
/// - `free_region_relations` -- something that can be used to relate
|
||||
/// the free regions (`'a`) that appear in the impl trait.
|
||||
fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>(
|
||||
&self,
|
||||
opaque_types: &OpaqueTypeMap<'tcx>,
|
||||
free_region_relations: &FRR,
|
||||
) {
|
||||
for &(opaque_type_key, opaque_defn) in opaque_types {
|
||||
fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>(&self, free_region_relations: &FRR) {
|
||||
let opaque_types = self.inner.borrow().opaque_types.clone();
|
||||
for (opaque_type_key, opaque_defn) in opaque_types {
|
||||
self.constrain_opaque_type(
|
||||
opaque_type_key,
|
||||
&opaque_defn,
|
||||
|
@ -403,19 +321,35 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
|
||||
let span = tcx.def_span(def_id);
|
||||
|
||||
// If there are required region bounds, we can use them.
|
||||
if opaque_defn.has_required_region_bounds {
|
||||
// Check if the `impl Trait` bounds include region bounds.
|
||||
// For example, this would be true for:
|
||||
//
|
||||
// fn foo<'a, 'b, 'c>() -> impl Trait<'c> + 'a + 'b
|
||||
//
|
||||
// but false for:
|
||||
//
|
||||
// fn foo<'c>() -> impl Trait<'c>
|
||||
//
|
||||
// unless `Trait` was declared like:
|
||||
//
|
||||
// trait Trait<'c>: 'c
|
||||
//
|
||||
// in which case it would be true.
|
||||
//
|
||||
// This is used during regionck to decide whether we need to
|
||||
// impose any additional constraints to ensure that region
|
||||
// variables in `concrete_ty` wind up being constrained to
|
||||
// something from `substs` (or, at minimum, things that outlive
|
||||
// the fn body). (Ultimately, writeback is responsible for this
|
||||
// check.)
|
||||
let bounds = tcx.explicit_item_bounds(def_id);
|
||||
debug!("{:#?}", bounds);
|
||||
let bounds: Vec<_> =
|
||||
bounds.iter().map(|(bound, _)| bound.subst(tcx, opaque_type_key.substs)).collect();
|
||||
let bounds = bounds.iter().map(|(bound, _)| bound.subst(tcx, opaque_type_key.substs));
|
||||
debug!("{:#?}", bounds);
|
||||
let opaque_type = tcx.mk_opaque(def_id, opaque_type_key.substs);
|
||||
|
||||
let required_region_bounds =
|
||||
required_region_bounds(tcx, opaque_type, bounds.into_iter());
|
||||
debug_assert!(!required_region_bounds.is_empty());
|
||||
|
||||
let required_region_bounds = required_region_bounds(tcx, opaque_type, bounds);
|
||||
if !required_region_bounds.is_empty() {
|
||||
for required_region in required_region_bounds {
|
||||
concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
|
||||
op: |r| self.sub_regions(infer::CallReturn(span), required_region, r),
|
||||
|
@ -914,11 +848,9 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
|
|||
|
||||
struct Instantiator<'a, 'tcx> {
|
||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||
parent_def_id: LocalDefId,
|
||||
body_id: hir::HirId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
value_span: Span,
|
||||
opaque_types: OpaqueTypeMap<'tcx>,
|
||||
obligations: Vec<PredicateObligation<'tcx>>,
|
||||
}
|
||||
|
||||
|
@ -968,7 +900,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
|
|||
// ```
|
||||
if let Some(def_id) = def_id.as_local() {
|
||||
let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
let parent_def_id = self.parent_def_id;
|
||||
let parent_def_id = self.infcx.defining_use_anchor;
|
||||
let def_scope_default = || {
|
||||
let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
|
||||
parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id)
|
||||
|
@ -980,14 +912,14 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
|
|||
impl_trait_fn: Some(parent),
|
||||
origin,
|
||||
..
|
||||
}) => (parent == self.parent_def_id.to_def_id(), origin),
|
||||
}) => (parent == parent_def_id.to_def_id(), origin),
|
||||
// Named `type Foo = impl Bar;`
|
||||
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
|
||||
impl_trait_fn: None,
|
||||
origin,
|
||||
..
|
||||
}) => (
|
||||
may_define_opaque_type(tcx, self.parent_def_id, opaque_hir_id),
|
||||
may_define_opaque_type(tcx, parent_def_id, opaque_hir_id),
|
||||
origin,
|
||||
),
|
||||
_ => (def_scope_default(), hir::OpaqueTyOrigin::TyAlias),
|
||||
|
@ -1028,32 +960,14 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
|
|||
|
||||
// Use the same type variable if the exact same opaque type appears more
|
||||
// than once in the return type (e.g., if it's passed to a type alias).
|
||||
if let Some(opaque_defn) = self.opaque_types.get(&opaque_type_key) {
|
||||
if let Some(opaque_defn) = infcx.inner.borrow().opaque_types.get(&opaque_type_key) {
|
||||
debug!("instantiate_opaque_types: returning concrete ty {:?}", opaque_defn.concrete_ty);
|
||||
return opaque_defn.concrete_ty;
|
||||
}
|
||||
let span = tcx.def_span(def_id);
|
||||
debug!("fold_opaque_ty {:?} {:?}", self.value_span, span);
|
||||
let ty_var = infcx
|
||||
.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
|
||||
|
||||
let item_bounds = tcx.explicit_item_bounds(def_id);
|
||||
debug!("instantiate_opaque_types: bounds={:#?}", item_bounds);
|
||||
let bounds: Vec<_> =
|
||||
item_bounds.iter().map(|(bound, _)| bound.subst(tcx, substs)).collect();
|
||||
|
||||
let param_env = tcx.param_env(def_id);
|
||||
let InferOk { value: bounds, obligations } = infcx.partially_normalize_associated_types_in(
|
||||
ObligationCause::misc(span, self.body_id),
|
||||
param_env,
|
||||
bounds,
|
||||
);
|
||||
self.obligations.extend(obligations);
|
||||
|
||||
debug!("instantiate_opaque_types: bounds={:?}", bounds);
|
||||
|
||||
let required_region_bounds = required_region_bounds(tcx, ty, bounds.iter().copied());
|
||||
debug!("instantiate_opaque_types: required_region_bounds={:?}", required_region_bounds);
|
||||
let ty_var = infcx.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::TypeInference,
|
||||
span: self.value_span,
|
||||
});
|
||||
|
||||
// Make sure that we are in fact defining the *entire* type
|
||||
// (e.g., `type Foo<T: Bound> = impl Bar;` needs to be
|
||||
|
@ -1068,23 +982,46 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
|
|||
// Foo, impl Bar)`.
|
||||
let definition_span = self.value_span;
|
||||
|
||||
self.opaque_types.insert(
|
||||
{
|
||||
let mut infcx = self.infcx.inner.borrow_mut();
|
||||
infcx.opaque_types.insert(
|
||||
OpaqueTypeKey { def_id, substs },
|
||||
OpaqueTypeDecl {
|
||||
opaque_type: ty,
|
||||
definition_span,
|
||||
concrete_ty: ty_var,
|
||||
has_required_region_bounds: !required_region_bounds.is_empty(),
|
||||
origin,
|
||||
},
|
||||
OpaqueTypeDecl { opaque_type: ty, definition_span, concrete_ty: ty_var, origin },
|
||||
);
|
||||
infcx.opaque_types_vars.insert(ty_var, ty);
|
||||
}
|
||||
|
||||
debug!("instantiate_opaque_types: ty_var={:?}", ty_var);
|
||||
self.compute_opaque_type_obligations(opaque_type_key);
|
||||
|
||||
ty_var
|
||||
}
|
||||
|
||||
fn compute_opaque_type_obligations(&mut self, opaque_type_key: OpaqueTypeKey<'tcx>) {
|
||||
let infcx = self.infcx;
|
||||
let tcx = infcx.tcx;
|
||||
let OpaqueTypeKey { def_id, substs } = opaque_type_key;
|
||||
|
||||
let item_bounds = tcx.explicit_item_bounds(def_id);
|
||||
debug!("instantiate_opaque_types: bounds={:#?}", item_bounds);
|
||||
let bounds: Vec<_> =
|
||||
item_bounds.iter().map(|(bound, _)| bound.subst(tcx, substs)).collect();
|
||||
|
||||
let param_env = tcx.param_env(def_id);
|
||||
let InferOk { value: bounds, obligations } = infcx.partially_normalize_associated_types_in(
|
||||
ObligationCause::misc(self.value_span, self.body_id),
|
||||
param_env,
|
||||
bounds,
|
||||
);
|
||||
self.obligations.extend(obligations);
|
||||
|
||||
debug!("instantiate_opaque_types: bounds={:?}", bounds);
|
||||
|
||||
for predicate in &bounds {
|
||||
if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() {
|
||||
if projection.ty.references_error() {
|
||||
// No point on adding these obligations since there's a type error involved.
|
||||
return ty_var;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1096,14 +1033,13 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
|
|||
// This also instantiates nested instances of `impl Trait`.
|
||||
let predicate = self.instantiate_opaque_types_in_map(predicate);
|
||||
|
||||
let cause = traits::ObligationCause::new(span, self.body_id, traits::OpaqueType);
|
||||
let cause =
|
||||
traits::ObligationCause::new(self.value_span, self.body_id, traits::OpaqueType);
|
||||
|
||||
// Require that the predicate holds for the concrete type.
|
||||
debug!("instantiate_opaque_types: predicate={:?}", predicate);
|
||||
self.obligations.push(traits::Obligation::new(cause, self.param_env, predicate));
|
||||
}
|
||||
|
||||
ty_var
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -593,13 +593,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
orig_expected: Expectation<'tcx>,
|
||||
) -> Option<Span> {
|
||||
match (orig_expected, self.ret_coercion_impl_trait.map(|ty| (self.body_id.owner, ty))) {
|
||||
(Expectation::ExpectHasType(expected), Some((id, ty)))
|
||||
(Expectation::ExpectHasType(expected), Some((_id, ty)))
|
||||
if self.in_tail_expr && self.can_coerce(outer_ty, expected) =>
|
||||
{
|
||||
let impl_trait_ret_ty =
|
||||
self.infcx.instantiate_opaque_types(id, self.body_id, self.param_env, ty, span);
|
||||
let mut suggest_box = !impl_trait_ret_ty.obligations.is_empty();
|
||||
for o in impl_trait_ret_ty.obligations {
|
||||
self.infcx.instantiate_opaque_types(self.body_id, self.param_env, ty, span);
|
||||
assert!(
|
||||
impl_trait_ret_ty.obligations.is_empty(),
|
||||
"we should never get new obligations here"
|
||||
);
|
||||
let obligations = self.fulfillment_cx.borrow().pending_obligations();
|
||||
let mut suggest_box = !obligations.is_empty();
|
||||
for o in obligations {
|
||||
match o.predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Trait(t, constness) => {
|
||||
let pred = ty::PredicateKind::Trait(
|
||||
|
|
|
@ -94,69 +94,8 @@ pub(super) fn check_fn<'a, 'tcx>(
|
|||
|
||||
let declared_ret_ty = fn_sig.output();
|
||||
|
||||
let feature = match tcx.hir().get(fn_id) {
|
||||
// TAIT usage in function return position.
|
||||
// Example:
|
||||
//
|
||||
// ```rust
|
||||
// type Foo = impl Debug;
|
||||
// fn bar() -> Foo { 42 }
|
||||
// ```
|
||||
Node::Item(hir::Item { kind: ItemKind::Fn(..), .. }) |
|
||||
// TAIT usage in associated function return position.
|
||||
//
|
||||
// Example with a free type alias:
|
||||
//
|
||||
// ```rust
|
||||
// type Foo = impl Debug;
|
||||
// impl SomeTrait for SomeType {
|
||||
// fn bar() -> Foo { 42 }
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Example with an associated TAIT:
|
||||
//
|
||||
// ```rust
|
||||
// impl SomeTrait for SomeType {
|
||||
// type Foo = impl Debug;
|
||||
// fn bar() -> Self::Foo { 42 }
|
||||
// }
|
||||
// ```
|
||||
Node::ImplItem(hir::ImplItem {
|
||||
kind: hir::ImplItemKind::Fn(..), ..
|
||||
}) => None,
|
||||
// Forbid TAIT in trait declarations for now.
|
||||
// Examples:
|
||||
//
|
||||
// ```rust
|
||||
// type Foo = impl Debug;
|
||||
// trait Bar {
|
||||
// fn bar() -> Foo;
|
||||
// }
|
||||
// trait Bop {
|
||||
// type Bop: PartialEq<Foo>;
|
||||
// }
|
||||
// ```
|
||||
Node::TraitItem(hir::TraitItem {
|
||||
kind: hir::TraitItemKind::Fn(..),
|
||||
..
|
||||
}) |
|
||||
// Forbid TAIT in closure return position for now.
|
||||
// Example:
|
||||
//
|
||||
// ```rust
|
||||
// type Foo = impl Debug;
|
||||
// let x = |y| -> Foo { 42 + y };
|
||||
// ```
|
||||
Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => Some(sym::type_alias_impl_trait),
|
||||
node => bug!("Item being checked wasn't a function/closure: {:?}", node),
|
||||
};
|
||||
let revealed_ret_ty = fcx.instantiate_opaque_types_from_value(
|
||||
fn_id,
|
||||
declared_ret_ty,
|
||||
decl.output.span(),
|
||||
feature,
|
||||
);
|
||||
let revealed_ret_ty =
|
||||
fcx.instantiate_opaque_types_from_value(declared_ret_ty, decl.output.span());
|
||||
debug!("check_fn: declared_ret_ty: {}, revealed_ret_ty: {}", declared_ret_ty, revealed_ret_ty);
|
||||
fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(revealed_ret_ty)));
|
||||
fcx.ret_type_span = Some(decl.output.span());
|
||||
|
@ -711,10 +650,11 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||
|
||||
let misc_cause = traits::ObligationCause::misc(span, hir_id);
|
||||
|
||||
let (_, opaque_type_map) = inh.register_infer_ok_obligations(
|
||||
infcx.instantiate_opaque_types(def_id, hir_id, param_env, opaque_ty, span),
|
||||
let _ = inh.register_infer_ok_obligations(
|
||||
infcx.instantiate_opaque_types(hir_id, param_env, opaque_ty, span),
|
||||
);
|
||||
|
||||
let opaque_type_map = infcx.inner.borrow().opaque_types.clone();
|
||||
for (OpaqueTypeKey { def_id, substs }, opaque_defn) in opaque_type_map {
|
||||
match infcx
|
||||
.at(&misc_cause, param_env)
|
||||
|
|
|
@ -29,12 +29,11 @@ use rustc_middle::ty::{
|
|||
};
|
||||
use rustc_session::lint;
|
||||
use rustc_session::lint::builtin::BARE_TRAIT_OBJECTS;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::hygiene::DesugaringKind;
|
||||
use rustc_span::source_map::{original_sp, DUMMY_SP};
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::{self, BytePos, MultiSpan, Span};
|
||||
use rustc_span::{hygiene::DesugaringKind, Symbol};
|
||||
use rustc_trait_selection::infer::InferCtxtExt as _;
|
||||
use rustc_trait_selection::opaque_types::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
|
||||
|
@ -363,50 +362,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
/// Replaces the opaque types from the given value with type variables,
|
||||
/// and records the `OpaqueTypeMap` for later use during writeback. See
|
||||
/// `InferCtxt::instantiate_opaque_types` for more details.
|
||||
#[instrument(skip(self, value_span), level = "debug")]
|
||||
pub(in super::super) fn instantiate_opaque_types_from_value<T: TypeFoldable<'tcx>>(
|
||||
&self,
|
||||
parent_id: hir::HirId,
|
||||
value: T,
|
||||
value_span: Span,
|
||||
feature: Option<Symbol>,
|
||||
) -> T {
|
||||
let parent_def_id = self.tcx.hir().local_def_id(parent_id);
|
||||
debug!(
|
||||
"instantiate_opaque_types_from_value(parent_def_id={:?}, value={:?})",
|
||||
parent_def_id, value
|
||||
);
|
||||
|
||||
let (value, opaque_type_map) =
|
||||
self.register_infer_ok_obligations(self.instantiate_opaque_types(
|
||||
parent_def_id,
|
||||
self.body_id,
|
||||
self.param_env,
|
||||
value,
|
||||
value_span,
|
||||
));
|
||||
|
||||
let mut opaque_types = self.opaque_types.borrow_mut();
|
||||
let mut opaque_types_vars = self.opaque_types_vars.borrow_mut();
|
||||
|
||||
for (ty, decl) in opaque_type_map {
|
||||
if let Some(feature) = feature {
|
||||
if let hir::OpaqueTyOrigin::TyAlias = decl.origin {
|
||||
if !self.tcx.features().enabled(feature) {
|
||||
feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
feature,
|
||||
value_span,
|
||||
"type alias impl trait is not permitted here",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
let _ = opaque_types.insert(ty, decl);
|
||||
let _ = opaque_types_vars.insert(decl.concrete_ty, decl.opaque_type);
|
||||
}
|
||||
|
||||
value
|
||||
))
|
||||
}
|
||||
|
||||
/// Convenience method which tracks extra diagnostic information for normalization
|
||||
|
@ -726,7 +693,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// We treat this as a non-defining use by making the inference
|
||||
// variable fall back to the opaque type itself.
|
||||
if let FallbackMode::All = mode {
|
||||
if let Some(opaque_ty) = self.opaque_types_vars.borrow().get(ty) {
|
||||
if let Some(opaque_ty) = self.infcx.inner.borrow().opaque_types_vars.get(ty) {
|
||||
debug!(
|
||||
"fallback_if_possible: falling back opaque type var {:?} to {:?}",
|
||||
ty, opaque_ty
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
use super::callee::DeferredCallResolution;
|
||||
use super::MaybeInProgressTables;
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::vec_map::VecMap;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefIdMap, LocalDefId};
|
||||
use rustc_hir::HirIdMap;
|
||||
use rustc_infer::infer;
|
||||
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
|
||||
use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::{self, Span};
|
||||
use rustc_trait_selection::infer::InferCtxtExt as _;
|
||||
use rustc_trait_selection::opaque_types::OpaqueTypeDecl;
|
||||
use rustc_trait_selection::traits::{self, ObligationCause, TraitEngine, TraitEngineExt};
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
@ -55,19 +52,6 @@ pub struct Inherited<'a, 'tcx> {
|
|||
pub(super) deferred_generator_interiors:
|
||||
RefCell<Vec<(hir::BodyId, Ty<'tcx>, hir::GeneratorKind)>>,
|
||||
|
||||
// Opaque types found in explicit return types and their
|
||||
// associated fresh inference variable. Writeback resolves these
|
||||
// variables to get the concrete type, which can be used to
|
||||
// 'de-opaque' OpaqueTypeDecl, after typeck is done with all functions.
|
||||
pub(super) opaque_types: RefCell<VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>>,
|
||||
|
||||
/// A map from inference variables created from opaque
|
||||
/// type instantiations (`ty::Infer`) to the actual opaque
|
||||
/// type (`ty::Opaque`). Used during fallback to map unconstrained
|
||||
/// opaque type inference variables to their corresponding
|
||||
/// opaque type.
|
||||
pub(super) opaque_types_vars: RefCell<FxHashMap<Ty<'tcx>, Ty<'tcx>>>,
|
||||
|
||||
pub(super) body_id: Option<hir::BodyId>,
|
||||
}
|
||||
|
||||
|
@ -124,8 +108,6 @@ impl Inherited<'a, 'tcx> {
|
|||
deferred_call_resolutions: RefCell::new(Default::default()),
|
||||
deferred_cast_checks: RefCell::new(Vec::new()),
|
||||
deferred_generator_interiors: RefCell::new(Vec::new()),
|
||||
opaque_types: RefCell::new(Default::default()),
|
||||
opaque_types_vars: RefCell::new(Default::default()),
|
||||
body_id,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -291,10 +291,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
|
|||
self.visit_body(body);
|
||||
self.visit_region_obligations(body_id.hir_id);
|
||||
|
||||
self.constrain_opaque_types(
|
||||
&self.fcx.opaque_types.borrow(),
|
||||
self.outlives_environment.free_region_map(),
|
||||
);
|
||||
self.constrain_opaque_types(self.outlives_environment.free_region_map());
|
||||
}
|
||||
|
||||
fn visit_region_obligations(&mut self, hir_id: hir::HirId) {
|
||||
|
|
|
@ -498,7 +498,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_opaque_types(&mut self, span: Span) {
|
||||
for &(opaque_type_key, opaque_defn) in self.fcx.opaque_types.borrow().iter() {
|
||||
let opaque_types = self.fcx.infcx.inner.borrow().opaque_types.clone();
|
||||
for (opaque_type_key, opaque_defn) in opaque_types {
|
||||
let hir_id =
|
||||
self.tcx().hir().local_def_id_to_hir_id(opaque_type_key.def_id.expect_local());
|
||||
let instantiated_ty = self.resolve(opaque_defn.concrete_ty, &hir_id);
|
||||
|
|
|
@ -28,9 +28,9 @@ impl Bar for AssocNoCopy {
|
|||
|
||||
impl Thing for AssocNoCopy {
|
||||
type Out = Box<dyn Bar<Assoc: Copy>>;
|
||||
//~^ ERROR the trait bound `String: Copy` is not satisfied
|
||||
|
||||
fn func() -> Self::Out {
|
||||
//~^ ERROR the trait bound `String: Copy` is not satisfied
|
||||
Box::new(AssocNoCopy)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error[E0277]: the trait bound `String: Copy` is not satisfied
|
||||
--> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:30:28
|
||||
--> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:32:18
|
||||
|
|
||||
LL | type Out = Box<dyn Bar<Assoc: Copy>>;
|
||||
| ^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
|
||||
LL | fn func() -> Self::Out {
|
||||
| ^^^^^^^^^ the trait `Copy` is not implemented for `String`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -8,12 +8,12 @@ pub trait Bar {
|
|||
|
||||
impl<S: Default> Bar for S {
|
||||
type E = impl Copy;
|
||||
//~^ ERROR the trait bound `S: Copy` is not satisfied in `(S, T)` [E0277]
|
||||
//~^^ ERROR the trait bound `T: Copy` is not satisfied in `(S, T)` [E0277]
|
||||
|
||||
fn foo<T: Default>() -> Self::E {
|
||||
//~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
|
||||
//~| ERROR impl has stricter requirements than trait
|
||||
//~| ERROR the trait bound `S: Copy` is not satisfied in `(S, T)` [E0277]
|
||||
//~| ERROR the trait bound `T: Copy` is not satisfied in `(S, T)` [E0277]
|
||||
(S::default(), T::default())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0276]: impl has stricter requirements than trait
|
||||
--> $DIR/issue-55872-1.rs:14:5
|
||||
--> $DIR/issue-55872-1.rs:12:5
|
||||
|
|
||||
LL | fn foo<T>() -> Self::E;
|
||||
| ----------------------- definition of `foo` from trait
|
||||
|
@ -8,10 +8,10 @@ LL | fn foo<T: Default>() -> Self::E {
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: Default`
|
||||
|
||||
error[E0277]: the trait bound `S: Copy` is not satisfied in `(S, T)`
|
||||
--> $DIR/issue-55872-1.rs:10:14
|
||||
--> $DIR/issue-55872-1.rs:12:29
|
||||
|
|
||||
LL | type E = impl Copy;
|
||||
| ^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S`
|
||||
LL | fn foo<T: Default>() -> Self::E {
|
||||
| ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S`
|
||||
|
|
||||
= note: required because it appears within the type `(S, T)`
|
||||
help: consider further restricting this bound
|
||||
|
@ -20,10 +20,10 @@ LL | impl<S: Default + std::marker::Copy> Bar for S {
|
|||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: the trait bound `T: Copy` is not satisfied in `(S, T)`
|
||||
--> $DIR/issue-55872-1.rs:10:14
|
||||
--> $DIR/issue-55872-1.rs:12:29
|
||||
|
|
||||
LL | type E = impl Copy;
|
||||
| ^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T`
|
||||
LL | fn foo<T: Default>() -> Self::E {
|
||||
| ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T`
|
||||
|
|
||||
= note: required because it appears within the type `(S, T)`
|
||||
help: consider further restricting this bound
|
||||
|
@ -32,12 +32,14 @@ LL | fn foo<T: Default + std::marker::Copy>() -> Self::E {
|
|||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
|
||||
--> $DIR/issue-55872-1.rs:14:37
|
||||
--> $DIR/issue-55872-1.rs:12:37
|
||||
|
|
||||
LL | fn foo<T: Default>() -> Self::E {
|
||||
| _____________________________________^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | (S::default(), T::default())
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
|
@ -11,9 +11,9 @@ pub trait Bar {
|
|||
|
||||
impl<S> Bar for S {
|
||||
type E = impl std::marker::Copy;
|
||||
//~^ ERROR the trait bound `impl Future: Copy` is not satisfied [E0277]
|
||||
fn foo<T>() -> Self::E {
|
||||
//~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
|
||||
//~| ERROR the trait bound `impl Future: Copy` is not satisfied [E0277]
|
||||
async {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
error[E0277]: the trait bound `impl Future: Copy` is not satisfied
|
||||
--> $DIR/issue-55872-2.rs:13:14
|
||||
--> $DIR/issue-55872-2.rs:14:20
|
||||
|
|
||||
LL | type E = impl std::marker::Copy;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future`
|
||||
LL | fn foo<T>() -> Self::E {
|
||||
| ^^^^^^^ the trait `Copy` is not implemented for `impl Future`
|
||||
|
||||
error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
|
||||
--> $DIR/issue-55872-2.rs:15:28
|
||||
--> $DIR/issue-55872-2.rs:14:28
|
||||
|
|
||||
LL | fn foo<T>() -> Self::E {
|
||||
| ____________________________^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | async {}
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
|
@ -19,7 +19,7 @@ LL | type WrongGeneric<T> = impl 'static;
|
|||
found opaque type `impl Sized`
|
||||
|
||||
error[E0310]: the parameter type `T` may not live long enough
|
||||
--> $DIR/generic_type_does_not_live_long_enough.rs:13:30
|
||||
--> $DIR/generic_type_does_not_live_long_enough.rs:12:30
|
||||
|
|
||||
LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -7,9 +7,9 @@ fn main() {
|
|||
}
|
||||
|
||||
type WrongGeneric<T> = impl 'static;
|
||||
//~^ ERROR the parameter type `T` may not live long enough
|
||||
//~| ERROR: at least one trait must be specified
|
||||
//~^ ERROR: at least one trait must be specified
|
||||
|
||||
fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
|
||||
//~^ ERROR the parameter type `T` may not live long enough
|
||||
t
|
||||
}
|
||||
|
|
|
@ -19,13 +19,12 @@ LL | type WrongGeneric<T> = impl 'static;
|
|||
found opaque type `impl Sized`
|
||||
|
||||
error[E0310]: the parameter type `T` may not live long enough
|
||||
--> $DIR/generic_type_does_not_live_long_enough.rs:9:24
|
||||
--> $DIR/generic_type_does_not_live_long_enough.rs:12:30
|
||||
|
|
||||
LL | type WrongGeneric<T> = impl 'static;
|
||||
| ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
||||
...
|
||||
LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
|
||||
| - help: consider adding an explicit lifetime bound...: `T: 'static`
|
||||
| - ^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
||||
| |
|
||||
| help: consider adding an explicit lifetime bound...: `T: 'static`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
@ -10,29 +10,5 @@ error: higher-ranked subtype error
|
|||
LL | |x| x
|
||||
| ^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-57611-trait-alias.rs:17:16
|
||||
|
|
||||
LL | type Bar = impl Baz<Self, Self>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected type `for<'r> Fn<(&'r X,)>`
|
||||
found type `Fn<(&'static X,)>`
|
||||
note: this closure does not fulfill the lifetime requirements
|
||||
--> $DIR/issue-57611-trait-alias.rs:21:9
|
||||
|
|
||||
LL | |x| x
|
||||
| ^^^^^
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
error: implementation of `FnOnce` is not general enough
|
||||
--> $DIR/issue-57611-trait-alias.rs:17:16
|
||||
|
|
||||
LL | type Bar = impl Baz<Self, Self>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'static X) -> &'static X` must implement `FnOnce<(&'0 X,)>`, for any lifetime `'0`...
|
||||
= note: ...but it actually implements `FnOnce<(&'static X,)>`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
@ -15,9 +15,9 @@ struct X;
|
|||
|
||||
impl Foo for X {
|
||||
type Bar = impl Baz<Self, Self>;
|
||||
//~^ ERROR implementation of `FnOnce` is not general enough
|
||||
|
||||
fn bar(&self) -> Self::Bar {
|
||||
//~^ ERROR implementation of `FnOnce` is not general enough
|
||||
|x| x
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error: implementation of `FnOnce` is not general enough
|
||||
--> $DIR/issue-57611-trait-alias.rs:17:16
|
||||
--> $DIR/issue-57611-trait-alias.rs:19:22
|
||||
|
|
||||
LL | type Bar = impl Baz<Self, Self>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
||||
LL | fn bar(&self) -> Self::Bar {
|
||||
| ^^^^^^^^^ implementation of `FnOnce` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'2 X) -> &X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
|
||||
= note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
|
||||
|
|
|
@ -8,10 +8,9 @@ trait Bug {
|
|||
|
||||
impl Bug for &() {
|
||||
type Item = impl Bug; //~ ERROR `impl Trait` in type aliases is unstable
|
||||
//~^ ERROR the trait bound `(): Bug` is not satisfied
|
||||
|
||||
const FUN: fn() -> Self::Item = || ();
|
||||
//~^ ERROR type alias impl trait is not permitted here
|
||||
//~^ ERROR the trait bound `(): Bug` is not satisfied
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -7,25 +7,16 @@ LL | type Item = impl Bug;
|
|||
= note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
|
||||
= help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: type alias impl trait is not permitted here
|
||||
--> $DIR/issue-60371.rs:13:40
|
||||
error[E0277]: the trait bound `(): Bug` is not satisfied
|
||||
--> $DIR/issue-60371.rs:12:40
|
||||
|
|
||||
LL | const FUN: fn() -> Self::Item = || ();
|
||||
| ^
|
||||
|
|
||||
= note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
|
||||
= help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
|
||||
|
||||
error[E0277]: the trait bound `(): Bug` is not satisfied
|
||||
--> $DIR/issue-60371.rs:10:17
|
||||
|
|
||||
LL | type Item = impl Bug;
|
||||
| ^^^^^^^^ the trait `Bug` is not implemented for `()`
|
||||
| ^ the trait `Bug` is not implemented for `()`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<&() as Bug>
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0658.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
type Closure = impl FnOnce(); //~ ERROR: type mismatch resolving
|
||||
type Closure = impl FnOnce();
|
||||
|
||||
fn c() -> Closure {
|
||||
|| -> Closure { || () }
|
||||
|| -> Closure { || () } //~ ERROR: mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
error[E0271]: type mismatch resolving `<[closure@$DIR/issue-63279.rs:8:5: 8:28] as FnOnce<()>>::Output == ()`
|
||||
--> $DIR/issue-63279.rs:5:16
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-63279.rs:8:5
|
||||
|
|
||||
LL | type Closure = impl FnOnce();
|
||||
| ^^^^^^^^^^^^^ expected `()`, found opaque type
|
||||
| ------------- the found opaque type
|
||||
...
|
||||
LL | || -> Closure { || () }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure
|
||||
|
|
||||
= note: expected unit type `()`
|
||||
found opaque type `impl FnOnce<()>`
|
||||
= note: expected type `[closure@$DIR/issue-63279.rs:8:21: 8:26]`
|
||||
found closure `[closure@$DIR/issue-63279.rs:8:5: 8:28]`
|
||||
= note: no two closures, even if identical, have the same type
|
||||
= help: consider boxing your closure and/or using it as a trait object
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// compile-flags: -Zsave-analysis
|
||||
// check-pass
|
||||
|
||||
#![feature(type_alias_impl_trait, rustc_attrs)]
|
||||
|
||||
|
@ -11,9 +12,7 @@ type T = impl Sized;
|
|||
|
||||
fn take(_: fn() -> T) {}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() {
|
||||
//~^ ERROR fatal error triggered by #[rustc_error]
|
||||
take(|| {});
|
||||
take(|| {});
|
||||
}
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
error: fatal error triggered by #[rustc_error]
|
||||
--> $DIR/issue-65679-inst-opaque-ty-from-val-twice.rs:15:1
|
||||
|
|
||||
LL | fn main() {
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
@ -6,8 +6,7 @@ type Test = impl Copy;
|
|||
|
||||
fn test() -> Test {
|
||||
let y = || -> Test { () };
|
||||
//~^ ERROR: concrete type differs from previous defining opaque type use
|
||||
7
|
||||
7 //~ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/issue-74280.rs:8:13
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-74280.rs:9:5
|
||||
|
|
||||
LL | let y = || -> Test { () };
|
||||
| ^^^^^^^^^^^^^^^^^ expected `i32`, got `()`
|
||||
|
|
||||
note: previous use here
|
||||
--> $DIR/issue-74280.rs:7:1
|
||||
|
|
||||
LL | fn test() -> Test {
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
LL | 7
|
||||
| ^ expected `()`, found integer
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
type X<A, B> = impl Into<&'static A>;
|
||||
//~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied
|
||||
|
||||
fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
|
||||
//~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied
|
||||
(a, a)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error[E0277]: the trait bound `&'static B: From<&A>` is not satisfied
|
||||
--> $DIR/multiple-def-uses-in-one-fn.rs:7:16
|
||||
--> $DIR/multiple-def-uses-in-one-fn.rs:9:45
|
||||
|
|
||||
LL | type X<A, B> = impl Into<&'static A>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<&A>` is not implemented for `&'static B`
|
||||
LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
|
||||
| ^^^^^^^^^^^^^^^^^^ the trait `From<&A>` is not implemented for `&'static B`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `Into<&'static B>` for `&A`
|
||||
help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue