diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index f0d63f512fcbc..10217a5f57498 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -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>>, } 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>>, + 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(&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), diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs new file mode 100644 index 0000000000000..d0883f23a4e6b --- /dev/null +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -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, 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, +} diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs index 36eb8a4baa830..2bfa51f27bbb6 100644 --- a/compiler/rustc_mir/src/borrow_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/mod.rs @@ -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) diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index 3fb06cd2f5f44..f69d08a6d5942 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -179,54 +179,55 @@ 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; - - for (_, revealed_ty) in &mut opaque_type_values { - *revealed_ty = infcx.resolve_vars_if_possible(*revealed_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(); - } - } - - opaque_type_values.retain(|(opaque_type_key, resolved_ty)| { - let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind() { - *def_id == opaque_type_key.def_id - } else { - false - }; + let opaque_type_values = mem::take(&mut infcx.inner.borrow_mut().opaque_types); - if concrete_is_opaque { - // We're using an opaque `impl Trait` type without - // 'revealing' it. For example, code like this: - // - // type Foo = impl Debug; - // fn foo1() -> Foo { ... } - // fn foo2() -> Foo { foo1() } - // - // In `foo2`, we're not revealing the type of `Foo` - we're - // just treating it as the opaque type. - // - // When this occurs, we do *not* want to try to equate - // the concrete type with the underlying defining type - // of the opaque type - this will always fail, since - // the defining type of an opaque type is always - // some other type (e.g. not itself) - // Essentially, none of the normal obligations apply here - - // we're just passing around some unknown opaque type, - // without actually looking at the underlying type it - // gets 'revealed' into - debug!( - "eq_opaque_type_and_type: non-defining use of {:?}", - opaque_type_key.def_id, - ); - } - !concrete_is_opaque - }); 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(); + } + let concrete_is_opaque = if let ty::Opaque(def_id, _) = revealed_ty.kind() { + *def_id == opaque_type_key.def_id + } else { + false + }; + + if concrete_is_opaque { + // We're using an opaque `impl Trait` type without + // 'revealing' it. For example, code like this: + // + // type Foo = impl Debug; + // fn foo1() -> Foo { ... } + // fn foo2() -> Foo { foo1() } + // + // In `foo2`, we're not revealing the type of `Foo` - we're + // just treating it as the opaque type. + // + // When this occurs, we do *not* want to try to equate + // the concrete type with the underlying defining type + // of the opaque type - this will always fail, since + // the defining type of an opaque type is always + // some other type (e.g. not itself) + // Essentially, none of the normal obligations apply here - + // we're just passing around some unknown opaque type, + // without actually looking at the underlying type it + // gets 'revealed' into + debug!( + "eq_opaque_type_and_type: non-defining use of {:?}", + opaque_type_key.def_id, + ); + None + } else { + Some((opaque_type_key, revealed_ty)) + } + }) + .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, 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,20 +1304,17 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // to `Box`, returning an `opaque_type_map` mapping `{Foo -> ?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, - dummy_body_id, - param_env, - anon_ty, - locations.span(body), - )); + let output_ty = obligations.add(infcx.instantiate_opaque_types( + dummy_body_id, + param_env, + anon_ty, + locations.span(body), + )); 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,48 +1332,38 @@ 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 { - for (opaque_type_key, opaque_decl) in opaque_type_map { - self.fully_perform_op( - locations, - ConstraintCategory::OpaqueType, - CustomTypeOp::new( - |infcx| { - infcx.constrain_opaque_type( - opaque_type_key, - &opaque_decl, - GenerateMemberConstraints::IfNoStaticBound, - universal_region_relations, - ); - Ok(InferOk { value: (), obligations: vec![] }) - }, - || "opaque_type_map".to_string(), - ), - )?; - } + 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, + ConstraintCategory::OpaqueType, + CustomTypeOp::new( + |infcx| { + infcx.constrain_opaque_type( + opaque_type_key, + &opaque_decl, + GenerateMemberConstraints::IfNoStaticBound, + universal_region_relations, + ); + Ok(InferOk { value: (), obligations: vec![] }) + }, + || "opaque_type_map".to_string(), + ), + )?; } Ok(()) } diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 95c81c5c729be..1a195ce18ec64 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -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, 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>( &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>( - &self, - opaque_types: &OpaqueTypeMap<'tcx>, - free_region_relations: &FRR, - ); + fn constrain_opaque_types>(&self, free_region_relations: &FRR); fn constrain_opaque_type>( &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>( &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>( - &self, - opaque_types: &OpaqueTypeMap<'tcx>, - free_region_relations: &FRR, - ) { - for &(opaque_type_key, opaque_defn) in opaque_types { + fn constrain_opaque_types>(&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 { - 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(); - 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()); - + // 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 = 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); + 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>, } @@ -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 = 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( - OpaqueTypeKey { def_id, substs }, - OpaqueTypeDecl { - opaque_type: ty, - definition_span, - concrete_ty: ty_var, - has_required_region_bounds: !required_region_bounds.is_empty(), - origin, - }, - ); + { + 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, 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 } } diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index dee81510b795b..10c3a97e73a5a 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -593,13 +593,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { orig_expected: Expectation<'tcx>, ) -> Option { 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( diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index ba99e0c03d8e2..8b5b7e3e52c80 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -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; - // } - // ``` - 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) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index f5776ae7cf66a..b84a79b768c9a 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -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>( &self, - parent_id: hir::HirId, value: T, value_span: Span, - feature: Option, ) -> 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 + self.register_infer_ok_obligations(self.instantiate_opaque_types( + self.body_id, + self.param_env, + value, + value_span, + )) } /// 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 diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs index 7e43e36fe55c6..fb7beae70ba1e 100644 --- a/compiler/rustc_typeck/src/check/inherited.rs +++ b/compiler/rustc_typeck/src/check/inherited.rs @@ -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, 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, 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, Ty<'tcx>>>, - pub(super) body_id: Option, } @@ -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, } } diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs index 8f8514cadb745..ca6828cfdf68d 100644 --- a/compiler/rustc_typeck/src/check/regionck.rs +++ b/compiler/rustc_typeck/src/check/regionck.rs @@ -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) { diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index e6eac16667d4e..959ab69a679eb 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -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); diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs index 7950dd3e99e29..4c36289f47b85 100644 --- a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs +++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs @@ -28,9 +28,9 @@ impl Bar for AssocNoCopy { impl Thing for AssocNoCopy { type Out = Box>; - //~^ 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) } } diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr index 0f1d35be0eb7a..a32ab453152a0 100644 --- a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr +++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr @@ -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>; - | ^^^^^^^^^^^ 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 diff --git a/src/test/ui/impl-trait/issue-55872-1.rs b/src/test/ui/impl-trait/issue-55872-1.rs index 72a060abae3e7..46188636475db 100644 --- a/src/test/ui/impl-trait/issue-55872-1.rs +++ b/src/test/ui/impl-trait/issue-55872-1.rs @@ -8,12 +8,12 @@ pub trait Bar { impl 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() -> 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()) } } diff --git a/src/test/ui/impl-trait/issue-55872-1.stderr b/src/test/ui/impl-trait/issue-55872-1.stderr index 6411c1b5d1ca2..56f5bff939fb7 100644 --- a/src/test/ui/impl-trait/issue-55872-1.stderr +++ b/src/test/ui/impl-trait/issue-55872-1.stderr @@ -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() -> Self::E; | ----------------------- definition of `foo` from trait @@ -8,10 +8,10 @@ LL | fn foo() -> 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() -> 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 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() -> 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() -> 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() -> Self::E { | _____________________________________^ LL | | LL | | +LL | | +LL | | LL | | (S::default(), T::default()) LL | | } | |_____^ diff --git a/src/test/ui/impl-trait/issue-55872-2.rs b/src/test/ui/impl-trait/issue-55872-2.rs index 6eda1dc62ec62..9546d01ac5c68 100644 --- a/src/test/ui/impl-trait/issue-55872-2.rs +++ b/src/test/ui/impl-trait/issue-55872-2.rs @@ -11,9 +11,9 @@ pub trait Bar { impl Bar for S { type E = impl std::marker::Copy; - //~^ ERROR the trait bound `impl Future: Copy` is not satisfied [E0277] fn foo() -> 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 {} } } diff --git a/src/test/ui/impl-trait/issue-55872-2.stderr b/src/test/ui/impl-trait/issue-55872-2.stderr index 58c5ee45051af..31b8fbd299c51 100644 --- a/src/test/ui/impl-trait/issue-55872-2.stderr +++ b/src/test/ui/impl-trait/issue-55872-2.stderr @@ -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() -> 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() -> Self::E { | ____________________________^ LL | | +LL | | LL | | async {} LL | | } | |_____^ diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr index 84f48cd6c0d20..f4e1de8e50f68 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr @@ -19,7 +19,7 @@ LL | type WrongGeneric = 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) -> WrongGeneric { | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs index 9c6b93b7ba040..78d25e30e0382 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs @@ -7,9 +7,9 @@ fn main() { } type WrongGeneric = 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) -> WrongGeneric { + //~^ ERROR the parameter type `T` may not live long enough t } diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr index 18d8daa05e63d..568784372e519 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr @@ -19,13 +19,12 @@ LL | type WrongGeneric = 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 = impl 'static; - | ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds -... LL | fn wrong_generic(t: T) -> WrongGeneric { - | - 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 diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr index a4ccae4eb7ed9..8c9cb742fac91 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr @@ -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; - | ^^^^^^^^^^^^^^^^^^^^ 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: implementation of `FnOnce` is not general enough - --> $DIR/issue-57611-trait-alias.rs:17:16 - | -LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ 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 +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs index a55fbf9c48a57..625e46b6bc012 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs @@ -15,9 +15,9 @@ struct X; impl Foo for X { type Bar = impl Baz; - //~^ ERROR implementation of `FnOnce` is not general enough fn bar(&self) -> Self::Bar { + //~^ ERROR implementation of `FnOnce` is not general enough |x| x } } diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr index f87beb66d995e..54d237159d80b 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr @@ -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; - | ^^^^^^^^^^^^^^^^^^^^ 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` diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.rs b/src/test/ui/type-alias-impl-trait/issue-60371.rs index cee5e5a01cc2a..37a2f28ce074f 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60371.rs +++ b/src/test/ui/type-alias-impl-trait/issue-60371.rs @@ -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() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.stderr b/src/test/ui/type-alias-impl-trait/issue-60371.stderr index 9abdd70bbd927..1710e07644d64 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60371.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60371.stderr @@ -7,25 +7,16 @@ LL | type Item = impl Bug; = note: see issue #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 - | -LL | const FUN: fn() -> Self::Item = || (); - | ^ - | - = note: see issue #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 + --> $DIR/issue-60371.rs:12:40 | -LL | type Item = impl Bug; - | ^^^^^^^^ the trait `Bug` is not implemented for `()` +LL | const FUN: fn() -> Self::Item = || (); + | ^ 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`. diff --git a/src/test/ui/type-alias-impl-trait/issue-63279.rs b/src/test/ui/type-alias-impl-trait/issue-63279.rs index b97192a2aed4a..875cce4df2390 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63279.rs +++ b/src/test/ui/type-alias-impl-trait/issue-63279.rs @@ -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() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-63279.stderr b/src/test/ui/type-alias-impl-trait/issue-63279.stderr index 63a83a60ff876..5fde8c2ef1e11 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63279.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-63279.stderr @@ -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`. diff --git a/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs b/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs index 0f0cd4e9227b4..72c22827f624b 100644 --- a/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs +++ b/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs @@ -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(|| {}); } diff --git a/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.stderr b/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.stderr deleted file mode 100644 index f3683f2bf9607..0000000000000 --- a/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.stderr +++ /dev/null @@ -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 - diff --git a/src/test/ui/type-alias-impl-trait/issue-74280.rs b/src/test/ui/type-alias-impl-trait/issue-74280.rs index d5b90a49b0521..ad641eaa00d38 100644 --- a/src/test/ui/type-alias-impl-trait/issue-74280.rs +++ b/src/test/ui/type-alias-impl-trait/issue-74280.rs @@ -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() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-74280.stderr b/src/test/ui/type-alias-impl-trait/issue-74280.stderr index 79c7df788f46c..f6b369dd8d518 100644 --- a/src/test/ui/type-alias-impl-trait/issue-74280.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-74280.stderr @@ -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`. diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs index 371dff475d1d7..da845e86147b7 100644 --- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs @@ -5,9 +5,9 @@ #![feature(type_alias_impl_trait)] type X = impl Into<&'static A>; -//~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied fn f(a: &'static A, b: B) -> (X, X) { + //~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied (a, a) } diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr index 731c6e2788dde..734f15a9283de 100644 --- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr @@ -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 = impl Into<&'static A>; - | ^^^^^^^^^^^^^^^^^^^^^ the trait `From<&A>` is not implemented for `&'static B` +LL | fn f(a: &'static A, b: B) -> (X, X) { + | ^^^^^^^^^^^^^^^^^^ 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