From d49b0746f6c0cf41e94e4bbd1592c52082a9cad7 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 13 Aug 2021 17:19:26 +0000 Subject: [PATCH 01/53] Add roll back infrastructure for opaque type caches --- compiler/rustc_borrowck/src/type_check/mod.rs | 6 +- compiler/rustc_data_structures/src/vec_map.rs | 5 ++ compiler/rustc_infer/src/infer/equate.rs | 7 +- compiler/rustc_infer/src/infer/mod.rs | 26 +++---- .../rustc_infer/src/infer/opaque_types.rs | 24 ++++--- .../src/infer/opaque_types/table.rs | 69 +++++++++++++++++++ compiler/rustc_infer/src/infer/undo_log.rs | 5 +- compiler/rustc_typeck/src/check/check.rs | 3 +- compiler/rustc_typeck/src/check/fallback.rs | 2 +- compiler/rustc_typeck/src/check/writeback.rs | 3 +- 10 files changed, 113 insertions(+), 37 deletions(-) create mode 100644 compiler/rustc_infer/src/infer/opaque_types/table.rs diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 73103643e3e16..75305d9c92311 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -190,7 +190,8 @@ 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 opaque_type_values = mem::take(&mut infcx.inner.borrow_mut().opaque_types); + let opaque_type_values = + infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); opaque_type_values .into_iter() @@ -1315,8 +1316,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // have to solve any bounds (e.g., `-> impl Iterator` needs to // prove that `T: Iterator` where `T` is the type we // instantiated it with). - let opaque_type_map = self.infcx.inner.borrow().opaque_types.clone(); - for (opaque_type_key, opaque_decl) in opaque_type_map { + for (opaque_type_key, opaque_decl) in self.infcx.opaque_types() { self.fully_perform_op( locations, ConstraintCategory::OpaqueType, diff --git a/compiler/rustc_data_structures/src/vec_map.rs b/compiler/rustc_data_structures/src/vec_map.rs index cc7ec9432faed..8f525230e7eec 100644 --- a/compiler/rustc_data_structures/src/vec_map.rs +++ b/compiler/rustc_data_structures/src/vec_map.rs @@ -30,6 +30,11 @@ where } } + /// Removes the entry from the map and returns the removed value + pub fn remove(&mut self, k: &K) -> Option { + self.0.iter().position(|(k2, _)| k2 == k).map(|pos| self.0.remove(pos).1) + } + /// Gets a reference to the value in the entry. pub fn get(&self, k: &Q) -> Option<&V> where diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index 90c0ff9226f77..06692be4f7265 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -66,17 +66,18 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> { self.relate(a, b) } + #[instrument(skip(self), level = "debug")] fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { - debug!("{}.tys({:?}, {:?})", self.tag(), a, b); if a == b { return Ok(a); } + trace!(a = ?a.kind(), b = ?b.kind()); + let infcx = self.fields.infcx; let a = infcx.inner.borrow_mut().type_variables().replace_if_possible(a); let b = infcx.inner.borrow_mut().type_variables().replace_if_possible(b); - - debug!("{}.tys: replacements ({:?}, {:?})", self.tag(), a, b); + trace!(a = ?a.kind(), b = ?b.kind(), "replacements"); match (a.kind(), b.kind()) { (&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index d1b24b332bdcc..6c7e079a724a5 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -5,7 +5,7 @@ pub use self::RegionVariableOrigin::*; pub use self::SubregionOrigin::*; pub use self::ValuePairs::*; -use self::opaque_types::OpaqueTypeMap; +use self::opaque_types::OpaqueTypeStorage; pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog}; use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine}; @@ -190,20 +190,10 @@ pub struct InferCtxtInner<'tcx> { /// that all type inference variables have been bound and so forth. region_obligations: Vec<(hir::HirId, RegionObligation<'tcx>)>, - undo_log: InferCtxtUndoLogs<'tcx>, + /// Caches for opaque type inference. + pub opaque_type_storage: OpaqueTypeStorage<'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 outside of type inference. - 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>>, + undo_log: InferCtxtUndoLogs<'tcx>, } impl<'tcx> InferCtxtInner<'tcx> { @@ -217,8 +207,7 @@ 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(), + opaque_type_storage: Default::default(), } } @@ -237,6 +226,11 @@ impl<'tcx> InferCtxtInner<'tcx> { self.type_variable_storage.with_log(&mut self.undo_log) } + #[inline] + fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'tcx> { + self.opaque_type_storage.with_log(&mut self.undo_log) + } + #[inline] fn int_unification_table( &mut self, diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index e7dca94806cb7..e3e48a7f890e5 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -14,6 +14,10 @@ use std::ops::ControlFlow; pub type OpaqueTypeMap<'tcx> = VecMap, OpaqueTypeDecl<'tcx>>; +mod table; + +pub use table::{OpaqueTypeStorage, OpaqueTypeTable}; + /// Information about the opaque types whose values we /// are inferring in this function (these are the `impl Trait` that /// appear in the return type). @@ -352,6 +356,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }; in_definition_scope.then_some(*origin) } + + pub fn opaque_types(&self) -> OpaqueTypeMap<'tcx> { + self.inner.borrow().opaque_type_storage.opaque_types() + } } // Visitor that requires that (almost) all regions in the type visited outlive @@ -513,7 +521,9 @@ 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) = infcx.inner.borrow().opaque_types.get(&opaque_type_key) { + if let Some(opaque_defn) = + infcx.inner.borrow().opaque_type_storage.get_decl(&opaque_type_key) + { debug!("re-using cached concrete type {:?}", opaque_defn.concrete_ty.kind()); return opaque_defn.concrete_ty; } @@ -530,14 +540,10 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { // Foo, impl Bar)`. let definition_span = self.value_span; - { - 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); - } + self.infcx.inner.borrow_mut().opaque_types().register( + OpaqueTypeKey { def_id, substs }, + OpaqueTypeDecl { opaque_type: ty, definition_span, concrete_ty: ty_var, origin }, + ); debug!("generated new type inference var {:?}", ty_var.kind()); diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs new file mode 100644 index 0000000000000..11eeeb08c9888 --- /dev/null +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -0,0 +1,69 @@ +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::undo_log::UndoLogs; +use rustc_middle::ty::{OpaqueTypeKey, Ty}; + +use crate::infer::InferCtxtUndoLogs; + +use super::{OpaqueTypeDecl, OpaqueTypeMap}; + +#[derive(Default)] +pub struct OpaqueTypeStorage<'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> OpaqueTypeStorage<'tcx> { + pub(crate) fn remove(&mut self, key: OpaqueTypeKey<'tcx>) { + match self.opaque_types.remove(&key) { + None => bug!("reverted opaque type inference that was never registered"), + Some(decl) => assert_ne!(self.opaque_types_vars.remove(decl.concrete_ty), None), + } + } + + pub fn get_decl(&self, key: &OpaqueTypeKey<'tcx>) -> Option<&OpaqueTypeDecl<'tcx>> { + self.opaque_types.get(key) + } + + pub fn get_opaque_type_for_infer_var(&self, key: Ty<'tcx>) -> Option> { + self.opaque_types_vars.get(key).copied() + } + + pub fn opaque_types(&self) -> OpaqueTypeMap<'tcx> { + self.opaque_types.clone() + } + + pub fn take_opaque_types(&mut self) -> OpaqueTypeMap<'tcx> { + std::mem::take(&mut self.opaque_types) + } + + #[inline] + pub(crate) fn with_log<'a>( + &'a mut self, + undo_log: &'a mut InferCtxtUndoLogs<'tcx>, + ) -> OpaqueTypeTable<'a, 'tcx> { + OpaqueTypeTable { storage: self, undo_log } + } +} +pub struct OpaqueTypeTable<'a, 'tcx> { + storage: &'a mut OpaqueTypeStorage<'tcx>, + + undo_log: &'a mut InferCtxtUndoLogs<'tcx>, +} + +impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> { + pub fn register(&mut self, key: OpaqueTypeKey<'tcx>, decl: OpaqueTypeDecl<'tcx>) { + self.undo_log.push(key); + self.storage.opaque_types.insert(key, decl); + self.storage.opaque_types_vars.insert(decl.concrete_ty, decl.opaque_type); + } +} diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs index 89db8f464b4e7..3c8a163de5482 100644 --- a/compiler/rustc_infer/src/infer/undo_log.rs +++ b/compiler/rustc_infer/src/infer/undo_log.rs @@ -4,7 +4,7 @@ use rustc_data_structures::snapshot_vec as sv; use rustc_data_structures::undo_log::{Rollback, UndoLogs}; use rustc_data_structures::unify as ut; use rustc_middle::infer::unify_key::RegionVidKey; -use rustc_middle::ty; +use rustc_middle::ty::{self, OpaqueTypeKey}; use crate::{ infer::{region_constraints, type_variable, InferCtxtInner}, @@ -18,6 +18,7 @@ pub struct Snapshot<'tcx> { /// Records the "undo" data for a single operation that affects some form of inference variable. pub(crate) enum UndoLog<'tcx> { + OpaqueTypes(OpaqueTypeKey<'tcx>), TypeVariables(type_variable::UndoLog<'tcx>), ConstUnificationTable(sv::UndoLog>>), IntUnificationTable(sv::UndoLog>), @@ -42,6 +43,7 @@ macro_rules! impl_from { // Upcast from a single kind of "undoable action" to the general enum impl_from! { + OpaqueTypes(OpaqueTypeKey<'tcx>), RegionConstraintCollector(region_constraints::UndoLog<'tcx>), TypeVariables(type_variable::UndoLog<'tcx>), @@ -64,6 +66,7 @@ impl_from! { impl<'tcx> Rollback> for InferCtxtInner<'tcx> { fn reverse(&mut self, undo: UndoLog<'tcx>) { match undo { + UndoLog::OpaqueTypes(key) => self.opaque_type_storage.remove(key), UndoLog::TypeVariables(undo) => self.type_variable_storage.reverse(undo), UndoLog::ConstUnificationTable(undo) => self.const_unification_storage.reverse(undo), UndoLog::IntUnificationTable(undo) => self.int_unification_storage.reverse(undo), diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 18a0a8767d45b..7983b6ea0b2c0 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -647,8 +647,7 @@ fn check_opaque_meets_bounds<'tcx>( 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 { + for (OpaqueTypeKey { def_id, substs }, opaque_defn) in infcx.opaque_types() { let hidden_type = tcx.type_of(def_id).subst(tcx, substs); trace!(?hidden_type); match infcx.at(&misc_cause, param_env).eq(opaque_defn.concrete_ty, hidden_type) { diff --git a/compiler/rustc_typeck/src/check/fallback.rs b/compiler/rustc_typeck/src/check/fallback.rs index e5da33d113e7c..d062a0cc55f4e 100644 --- a/compiler/rustc_typeck/src/check/fallback.rs +++ b/compiler/rustc_typeck/src/check/fallback.rs @@ -176,7 +176,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { .type_var_origin(ty) .map(|origin| origin.span) .unwrap_or(rustc_span::DUMMY_SP); - let oty = self.inner.borrow().opaque_types_vars.get(ty).copied(); + let oty = self.inner.borrow().opaque_type_storage.get_opaque_type_for_infer_var(ty); if let Some(opaque_ty) = oty { debug!( "fallback_opaque_type_vars(ty={:?}): falling back to opaque type {:?}", diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index ec88bdf4a370f..165ca1574cd94 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -498,8 +498,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { #[instrument(skip(self, span), level = "debug")] fn visit_opaque_types(&mut self, span: Span) { - let opaque_types = self.fcx.infcx.inner.borrow().opaque_types.clone(); - for (opaque_type_key, opaque_defn) in opaque_types { + for (opaque_type_key, opaque_defn) in self.fcx.infcx.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); From a4c1cec4f8d27fcff7a3fca2276bec5e767696e9 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 20 Aug 2021 13:33:06 +0000 Subject: [PATCH 02/53] Add some sanity assertions to make sure we use the opaque types correctly --- compiler/rustc_infer/src/infer/opaque_types/table.rs | 12 +++++++++++- compiler/rustc_typeck/src/check/writeback.rs | 4 +++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs index 11eeeb08c9888..6b5d55784b2c9 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/table.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -6,7 +6,7 @@ use crate::infer::InferCtxtUndoLogs; use super::{OpaqueTypeDecl, OpaqueTypeMap}; -#[derive(Default)] +#[derive(Default, Debug)] pub struct OpaqueTypeStorage<'tcx> { // Opaque types found in explicit return types and their // associated fresh inference variable. Writeback resolves these @@ -23,6 +23,7 @@ pub struct OpaqueTypeStorage<'tcx> { } impl<'tcx> OpaqueTypeStorage<'tcx> { + #[instrument(level = "debug")] pub(crate) fn remove(&mut self, key: OpaqueTypeKey<'tcx>) { match self.opaque_types.remove(&key) { None => bug!("reverted opaque type inference that was never registered"), @@ -42,6 +43,7 @@ impl<'tcx> OpaqueTypeStorage<'tcx> { self.opaque_types.clone() } + #[instrument(level = "debug")] pub fn take_opaque_types(&mut self) -> OpaqueTypeMap<'tcx> { std::mem::take(&mut self.opaque_types) } @@ -54,6 +56,13 @@ impl<'tcx> OpaqueTypeStorage<'tcx> { OpaqueTypeTable { storage: self, undo_log } } } + +impl<'tcx> Drop for OpaqueTypeStorage<'tcx> { + fn drop(&mut self) { + assert!(self.opaque_types.is_empty(), "{:?}", self.opaque_types); + } +} + pub struct OpaqueTypeTable<'a, 'tcx> { storage: &'a mut OpaqueTypeStorage<'tcx>, @@ -61,6 +70,7 @@ pub struct OpaqueTypeTable<'a, 'tcx> { } impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> { + #[instrument(skip(self), level = "debug")] pub fn register(&mut self, key: OpaqueTypeKey<'tcx>, decl: OpaqueTypeDecl<'tcx>) { self.undo_log.push(key); self.storage.opaque_types.insert(key, decl); diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 165ca1574cd94..e4c9cdbeef3f4 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -498,7 +498,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { #[instrument(skip(self, span), level = "debug")] fn visit_opaque_types(&mut self, span: Span) { - for (opaque_type_key, opaque_defn) in self.fcx.infcx.opaque_types() { + let opaque_types = + self.fcx.infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); + 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); From bbbdcb327f49274cf48a3d010c715dcdc3999d81 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 20 Aug 2021 13:36:30 +0000 Subject: [PATCH 03/53] Update some comments --- compiler/rustc_middle/src/ty/sty.rs | 1 + compiler/rustc_typeck/src/check/upvar.rs | 5 ----- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 7d4af6cfa4052..a53d5f6626bb2 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -152,6 +152,7 @@ pub enum TyKind<'tcx> { /// The anonymous type of a closure. Used to represent the type of /// `|a| a`. + /// For the order of the substs see the `ClosureSubsts` type's documentation. Closure(DefId, SubstsRef<'tcx>), /// The anonymous type of a generator. Used to represent the type of diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index becae6c9dc920..0482e8b895b56 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -335,11 +335,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Returns a list of `Ty`s for each upvar. fn final_upvar_tys(&self, closure_id: DefId) -> Vec> { - // Presently an unboxed closure type cannot "escape" out of a - // function, so we will only encounter ones that originated in the - // local crate or were inlined into it along with some function. - // This may change if abstract return types of some sort are - // implemented. self.typeck_results .borrow() .closure_min_captures_flattened(closure_id) From 4e1a5968f13b19f16b88a52de1aa9fade94d469a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 20 Aug 2021 13:56:54 +0000 Subject: [PATCH 04/53] Found suspicious comparison of constants --- compiler/rustc_borrowck/src/type_check/relate_tys.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index cc3fe0a123c55..0b5171680ad52 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -117,6 +117,9 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> // We don't have to worry about the equality of consts during borrow checking // as consts always have a static lifetime. + // FIXME(oli-obk): is this really true? We can at least have HKL and with + // inline consts we may have further lifetimes that may be unsound to treat as + // 'static. fn const_equate(&mut self, _a: &'tcx Const<'tcx>, _b: &'tcx Const<'tcx>) {} fn normalization() -> NormalizationStrategy { From 47a6a24d516de34c9b613f71657e7c907978716d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 3 Sep 2021 14:46:26 +0000 Subject: [PATCH 05/53] Add a convenient way to inject rustc flags somewhere late in the bootstrap pipeline without causing rebuilds Useful for -Ztreat-err-as-bug --- src/bootstrap/bin/rustc.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 7105a2457e282..d9467e8fd6bc1 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -147,6 +147,12 @@ fn main() { cmd.arg("-Z").arg("force-unstable-if-unmarked"); } + if let Ok(flags) = env::var("MAGIC_EXTRA_RUSTFLAGS") { + for flag in flags.split(' ') { + cmd.arg(flag); + } + } + let is_test = args.iter().any(|a| a == "--test"); if verbose > 2 { let rust_env_vars = From f7abc1b6f86ff2eb4a9bd3fe659db0f2badc077d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 20 Aug 2021 13:58:01 +0000 Subject: [PATCH 06/53] Expose current span to type equality checking in nll --- compiler/rustc_borrowck/src/type_check/relate_tys.rs | 8 ++++++++ .../rustc_infer/src/infer/canonical/query_response.rs | 5 +++++ compiler/rustc_infer/src/infer/nll_relate/mod.rs | 2 ++ 3 files changed, 15 insertions(+) diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 0b5171680ad52..18d880b8de314 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -3,6 +3,7 @@ use rustc_infer::infer::NllRegionVariableOrigin; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::{self, Const, Ty}; +use rustc_span::{Span, DUMMY_SP}; use rustc_trait_selection::traits::query::Fallible; use crate::constraints::OutlivesConstraint; @@ -63,6 +64,13 @@ impl<'me, 'bccx, 'tcx> NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { } impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { + fn span(&self) -> Span { + match self.locations { + Locations::All(span) => span, + Locations::Single(_) => DUMMY_SP, + } + } + fn param_env(&self) -> ty::ParamEnv<'tcx> { self.type_checker.param_env } diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 5b4a9d9dfad45..fd41114d57561 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -26,6 +26,7 @@ use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; use rustc_middle::ty::{self, BoundVar, Const, ToPredicate, Ty, TyCtxt}; +use rustc_span::Span; use std::fmt::Debug; use std::iter; @@ -631,6 +632,10 @@ struct QueryTypeRelatingDelegate<'a, 'tcx> { } impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> { + fn span(&self) -> Span { + self.cause.span + } + fn param_env(&self) -> ty::ParamEnv<'tcx> { self.param_env } diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 0a210ed053ce4..95de2d40bb9c9 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -29,6 +29,7 @@ use rustc_middle::ty::error::TypeError; use rustc_middle::ty::fold::{TypeFoldable, TypeVisitor}; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{self, InferConst, Ty, TyCtxt}; +use rustc_span::Span; use std::fmt::Debug; use std::ops::ControlFlow; @@ -75,6 +76,7 @@ where pub trait TypeRelatingDelegate<'tcx> { fn param_env(&self) -> ty::ParamEnv<'tcx>; + fn span(&self) -> Span; /// Push a constraint `sup: sub` -- this constraint must be /// satisfied for the two types to be related. `sub` and `sup` may From 8d2b5984597202489c5e42461db530fa48e45a8e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 20 Aug 2021 14:39:06 +0000 Subject: [PATCH 07/53] More sanity checks --- compiler/rustc_infer/src/infer/opaque_types/table.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs index 6b5d55784b2c9..a660cfaf9462c 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/table.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -1,6 +1,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::undo_log::UndoLogs; -use rustc_middle::ty::{OpaqueTypeKey, Ty}; +use rustc_middle::ty::{self, OpaqueTypeKey, Ty}; +use rustc_span::DUMMY_SP; use crate::infer::InferCtxtUndoLogs; @@ -59,7 +60,11 @@ impl<'tcx> OpaqueTypeStorage<'tcx> { impl<'tcx> Drop for OpaqueTypeStorage<'tcx> { fn drop(&mut self) { - assert!(self.opaque_types.is_empty(), "{:?}", self.opaque_types); + if !self.opaque_types.is_empty() { + ty::tls::with(|tcx| { + tcx.sess.delay_span_bug(DUMMY_SP, &format!("{:?}", self.opaque_types)) + }); + } } } From 0f6e06b7c0262a6940b5161f3ac507084e7daea6 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 20 Aug 2021 14:47:12 +0000 Subject: [PATCH 08/53] Lazily resolve type-alias-impl-trait defining uses by using an opaque type obligation to bubble up comparisons between opaque types and other types Also uses proper obligation causes so that the body id works, because out of some reason nll uses body ids for logic instead of just diagnostics. --- compiler/rustc_borrowck/src/lib.rs | 5 +- .../src/region_infer/opaque_types.rs | 52 ++- .../src/type_check/input_output.rs | 8 +- compiler/rustc_borrowck/src/type_check/mod.rs | 233 +++------- .../src/type_check/relate_tys.rs | 60 ++- .../rustc_borrowck/src/universal_regions.rs | 14 +- .../src/transform/check_consts/check.rs | 20 +- .../src/transform/validate.rs | 5 +- compiler/rustc_data_structures/src/vec_map.rs | 11 +- compiler/rustc_infer/src/infer/at.rs | 20 +- .../src/infer/canonical/query_response.rs | 67 ++- compiler/rustc_infer/src/infer/combine.rs | 26 +- compiler/rustc_infer/src/infer/equate.rs | 17 +- compiler/rustc_infer/src/infer/freshen.rs | 4 +- compiler/rustc_infer/src/infer/glb.rs | 10 +- compiler/rustc_infer/src/infer/lattice.rs | 27 +- compiler/rustc_infer/src/infer/lub.rs | 10 +- compiler/rustc_infer/src/infer/mod.rs | 41 +- .../rustc_infer/src/infer/nll_relate/mod.rs | 37 +- .../rustc_infer/src/infer/opaque_types.rs | 438 ++++++++++++------ .../src/infer/opaque_types/table.rs | 46 +- .../rustc_infer/src/infer/outlives/mod.rs | 1 + .../src/infer/outlives/obligations.rs | 3 +- compiler/rustc_infer/src/infer/sub.rs | 39 +- compiler/rustc_infer/src/infer/undo_log.rs | 5 +- compiler/rustc_infer/src/traits/util.rs | 3 + compiler/rustc_lint/src/builtin.rs | 1 + compiler/rustc_middle/src/infer/canonical.rs | 5 +- compiler/rustc_middle/src/ty/_match.rs | 4 +- compiler/rustc_middle/src/ty/flags.rs | 4 + compiler/rustc_middle/src/ty/fold.rs | 16 +- compiler/rustc_middle/src/ty/mod.rs | 20 +- compiler/rustc_middle/src/ty/print/pretty.rs | 3 + .../rustc_middle/src/ty/structural_impls.rs | 6 + compiler/rustc_middle/src/ty/sty.rs | 7 + compiler/rustc_mir_build/src/build/block.rs | 6 +- .../src/dep_graph/serialized.rs | 2 - .../rustc_trait_selection/src/opaque_types.rs | 1 + .../src/traits/auto_trait.rs | 1 + .../src/traits/error_reporting/mod.rs | 4 + .../src/traits/fulfill.rs | 17 + .../src/traits/object_safety.rs | 2 + .../src/traits/query/type_op/custom.rs | 4 +- .../src/traits/select/candidate_assembly.rs | 1 + .../src/traits/select/mod.rs | 47 +- .../rustc_trait_selection/src/traits/wf.rs | 4 + compiler/rustc_traits/src/chalk/lowering.rs | 4 + compiler/rustc_traits/src/chalk/mod.rs | 2 + .../src/implied_outlives_bounds.rs | 1 + .../src/normalize_erasing_regions.rs | 1 + compiler/rustc_type_ir/src/lib.rs | 6 + compiler/rustc_typeck/src/check/_match.rs | 10 +- compiler/rustc_typeck/src/check/callee.rs | 2 +- compiler/rustc_typeck/src/check/check.rs | 50 +- compiler/rustc_typeck/src/check/closure.rs | 95 +++- compiler/rustc_typeck/src/check/coercion.rs | 2 +- .../rustc_typeck/src/check/expectation.rs | 28 +- compiler/rustc_typeck/src/check/fallback.rs | 67 +-- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 20 +- compiler/rustc_typeck/src/check/inherited.rs | 13 +- .../rustc_typeck/src/check/method/probe.rs | 4 + compiler/rustc_typeck/src/check/mod.rs | 16 + compiler/rustc_typeck/src/check/wfcheck.rs | 2 +- compiler/rustc_typeck/src/check/writeback.rs | 64 +-- compiler/rustc_typeck/src/collect/type_of.rs | 29 +- .../src/impl_wf_check/min_specialization.rs | 1 + .../rustc_typeck/src/outlives/explicit.rs | 1 + src/librustdoc/clean/mod.rs | 1 + .../incremental/hashes/function_interfaces.rs | 2 +- .../assoc-type-eq-with-dyn-atb-fail.rs | 3 +- .../assoc-type-eq-with-dyn-atb-fail.stderr | 16 +- .../impl-trait-return-missing-constraint.rs | 2 +- ...mpl-trait-return-missing-constraint.stderr | 14 +- ...async-borrowck-escaping-block-error.stderr | 6 +- src/test/ui/async-await/async-error-span.rs | 3 +- .../ui/async-await/async-error-span.stderr | 4 +- .../async-await/issue-64130-4-async-move.rs | 2 +- .../issue-64130-4-async-move.stderr | 12 +- src/test/ui/async-await/issue-70818.rs | 2 +- src/test/ui/async-await/issue-70818.stderr | 8 +- .../async-await/issue-70935-complex-spans.rs | 2 +- .../issue-70935-complex-spans.stderr | 11 +- .../ret-impl-trait-one.nll.stderr | 11 +- .../ret-impl-trait-one.stderr | 26 +- src/test/ui/async-await/no-const-async.rs | 1 + src/test/ui/async-await/no-const-async.stderr | 33 +- .../recursive-async-impl-trait-type.rs | 3 +- .../ui/async-await/suggest-missing-await.rs | 1 - .../async-await/suggest-missing-await.stderr | 27 +- src/test/ui/cast/casts-differing-anon.rs | 2 +- src/test/ui/cast/casts-differing-anon.stderr | 16 +- .../diagnostics/borrowck/borrowck-4.stderr | 6 +- src/test/ui/conservative_impl_trait.stderr | 9 +- .../defaults/rp_impl_trait_fail.rs | 6 +- .../defaults/rp_impl_trait_fail.stderr | 18 +- ...orted_main_const_fn_item_type_forbidden.rs | 2 - ...d_main_const_fn_item_type_forbidden.stderr | 23 +- .../feature-gate-type_alias_impl_trait.rs | 11 +- .../feature-gate-type_alias_impl_trait.stderr | 73 --- src/test/ui/generator/issue-88653.rs | 4 +- src/test/ui/generator/issue-88653.stderr | 19 +- .../type-mismatch-signature-deduction.rs | 4 +- .../type-mismatch-signature-deduction.stderr | 16 +- .../generic-associated-types/issue-87258_a.rs | 3 +- .../issue-87258_a.stderr | 11 +- .../generic-associated-types/issue-87258_b.rs | 3 +- .../issue-87258_b.stderr | 11 +- .../issue-88595.stderr | 4 +- .../issue-92096.migrate.stderr | 18 +- .../generic-associated-types/issue-92096.rs | 4 +- src/test/ui/impl-trait/auto-trait-leak.rs | 1 + src/test/ui/impl-trait/auto-trait-leak.stderr | 112 ++++- .../ui/impl-trait/bound-normalization-fail.rs | 6 +- .../bound-normalization-fail.stderr | 24 +- .../does-not-live-long-enough.stderr | 6 +- src/test/ui/impl-trait/equality.rs | 4 +- src/test/ui/impl-trait/equality.stderr | 24 +- src/test/ui/impl-trait/equality2.stderr | 4 +- src/test/ui/impl-trait/fallback.rs | 9 + src/test/ui/impl-trait/hidden-lifetimes.rs | 4 +- .../ui/impl-trait/hidden-lifetimes.stderr | 16 +- src/test/ui/impl-trait/issue-55872-1.rs | 8 +- src/test/ui/impl-trait/issue-55872-1.stderr | 31 +- src/test/ui/impl-trait/issue-55872-2.rs | 7 +- src/test/ui/impl-trait/issue-55872-2.stderr | 20 +- src/test/ui/impl-trait/issue-55872-3.rs | 21 + src/test/ui/impl-trait/issue-55872-3.stderr | 15 + src/test/ui/impl-trait/issue-55872.rs | 2 +- src/test/ui/impl-trait/issue-55872.stderr | 10 +- src/test/ui/impl-trait/issue-72911.rs | 3 +- src/test/ui/impl-trait/issue-72911.stderr | 30 +- src/test/ui/impl-trait/issues/issue-70877.rs | 4 +- .../ui/impl-trait/issues/issue-70877.stderr | 20 - src/test/ui/impl-trait/issues/issue-78722.rs | 3 +- .../ui/impl-trait/issues/issue-78722.stderr | 31 +- src/test/ui/impl-trait/issues/issue-86201.rs | 4 +- .../ui/impl-trait/issues/issue-86201.stderr | 21 - src/test/ui/impl-trait/lifetimes2.rs | 10 + .../multiple-lifetimes/error-handling-2.rs | 2 +- .../error-handling-2.stderr | 9 +- .../ordinary-bounds-unrelated.rs | 3 +- .../ordinary-bounds-unrelated.stderr | 25 +- .../ordinary-bounds-unsuited.rs | 3 +- .../ordinary-bounds-unsuited.stderr | 25 +- ...t_outlive_least_region_or_bound.nll.stderr | 22 +- .../must_outlive_least_region_or_bound.rs | 4 +- .../must_outlive_least_region_or_bound.stderr | 49 +- ...trait-in-return-position-impl-trait.stderr | 31 +- ...-to-type-err-cause-on-impl-trait-return.rs | 12 +- ...type-err-cause-on-impl-trait-return.stderr | 178 ++----- ...rojection-mismatch-in-impl-where-clause.rs | 2 +- ...ction-mismatch-in-impl-where-clause.stderr | 8 +- src/test/ui/impl-trait/question_mark.rs | 13 + .../recursive-impl-trait-type-direct.rs | 3 +- .../recursive-impl-trait-type-direct.stderr | 12 - .../recursive-impl-trait-type-indirect.rs | 2 +- .../ui/impl-trait/region-escape-via-bound.rs | 2 +- .../impl-trait/region-escape-via-bound.stderr | 8 +- .../static-return-lifetime-infered.rs | 4 +- .../static-return-lifetime-infered.stderr | 32 +- .../type_parameters_captured.nll.stderr | 6 +- .../ui/impl-trait/type_parameters_captured.rs | 2 +- .../type_parameters_captured.stderr | 8 +- src/test/ui/impl-trait/where-allowed-2.rs | 7 +- src/test/ui/impl-trait/where-allowed-2.stderr | 13 - src/test/ui/issues-71798.rs | 3 +- src/test/ui/issues-71798.stderr | 8 +- .../lang-item-missing-generator.stderr | 4 +- .../freeze_cycle.rs | 46 ++ .../infer_cross_function.rs | 27 ++ .../lifetime_inference.rs | 7 + .../ui/lazy-type-alias-impl-trait/nested.rs | 23 + .../opaque_vs_opaque.rs | 10 + .../unsized_sized_opaque.rs | 16 + .../lifetime-elision-return-type-trait.rs | 2 +- .../lifetime-elision-return-type-trait.stderr | 6 +- .../feature-gate-never_type_fallback.rs | 7 +- .../feature-gate-never_type_fallback.stderr | 12 +- src/test/ui/never_type/impl_trait_fallback.rs | 10 + .../ui/never_type/impl_trait_fallback2.rs | 21 + .../ui/never_type/impl_trait_fallback2.stderr | 9 + .../ui/never_type/impl_trait_fallback3.rs | 15 + .../ui/never_type/impl_trait_fallback3.stderr | 8 + .../ui/never_type/impl_trait_fallback4.rs | 24 + .../ui/never_type/impl_trait_fallback4.stderr | 9 + src/test/ui/nll/issue-52113.rs | 4 +- src/test/ui/nll/issue-52113.stderr | 2 +- src/test/ui/nll/issue-73159-rpit-static.rs | 2 +- .../ui/nll/issue-73159-rpit-static.stderr | 5 +- .../ui/nll/ty-outlives/impl-trait-captures.rs | 2 +- .../ty-outlives/impl-trait-captures.stderr | 2 +- .../ui/nll/ty-outlives/impl-trait-outlives.rs | 4 +- .../ty-outlives/impl-trait-outlives.stderr | 12 +- src/test/ui/parser/fn-header-semantic-fail.rs | 7 +- .../ui/parser/fn-header-semantic-fail.stderr | 154 ++++-- src/test/ui/polymorphization/generators.rs | 2 - .../ui/polymorphization/generators.stderr | 20 +- ...ue-70736-async-fn-no-body-def-collector.rs | 1 - ...0736-async-fn-no-body-def-collector.stderr | 23 +- ...types_pin_lifetime_impl_trait-async.stderr | 11 +- ..._self_types_pin_lifetime_impl_trait.stderr | 4 +- ...mpl-trait-return-trailing-semicolon.stderr | 11 +- src/test/ui/suggestions/issue-81098.stderr | 20 +- .../trait-object-nested-in-impl-trait.stderr | 52 ++- .../match-prev-arm-needing-semi.rs | 9 +- .../match-prev-arm-needing-semi.stderr | 27 +- .../ui/suggestions/opaque-type-error.stderr | 7 +- .../type-alias-impl-trait/argument-types.rs | 4 +- .../argument-types.stderr | 17 - .../auto-trait-leakage3.rs | 1 + .../auto-trait-leakage3.stderr | 27 +- .../type-alias-impl-trait/bound_reduction2.rs | 2 +- .../bound_reduction2.stderr | 15 +- .../bounds-are-checked.rs | 3 +- .../bounds-are-checked.stderr | 23 +- .../declared_but_not_defined_in_scope.stderr | 4 +- .../different_defining_uses_never_type.rs | 4 +- .../different_defining_uses_never_type.stderr | 26 -- .../ui/type-alias-impl-trait/field-types.rs | 4 +- .../type-alias-impl-trait/field-types.stderr | 21 - .../generic_duplicate_lifetime_param.rs | 2 +- .../generic_duplicate_lifetime_param.stderr | 6 +- .../generic_duplicate_param_use.rs | 6 +- .../generic_duplicate_param_use.stderr | 18 +- .../generic_duplicate_param_use2.rs | 2 +- .../generic_duplicate_param_use2.stderr | 6 +- .../generic_duplicate_param_use3.rs | 2 +- .../generic_duplicate_param_use3.stderr | 6 +- .../generic_duplicate_param_use4.rs | 2 +- .../generic_duplicate_param_use4.stderr | 6 +- .../generic_nondefining_use.rs | 6 +- .../generic_nondefining_use.stderr | 18 +- .../type-alias-impl-trait/generic_not_used.rs | 2 +- .../generic_not_used.stderr | 10 +- ..._type_does_not_live_long_enough.nll.stderr | 29 +- .../generic_type_does_not_live_long_enough.rs | 6 +- ...eric_type_does_not_live_long_enough.stderr | 37 +- .../type-alias-impl-trait/inference-cycle.rs | 6 +- .../inference-cycle.stderr | 50 +- .../ui/type-alias-impl-trait/issue-53598.rs | 2 +- .../type-alias-impl-trait/issue-53598.stderr | 10 +- .../issue-57611-trait-alias.rs | 3 +- .../issue-57611-trait-alias.stderr | 14 +- .../ui/type-alias-impl-trait/issue-57700.rs | 2 +- .../type-alias-impl-trait/issue-57700.stderr | 10 +- .../ui/type-alias-impl-trait/issue-58951-2.rs | 18 + .../ui/type-alias-impl-trait/issue-60371.rs | 2 +- .../type-alias-impl-trait/issue-60371.stderr | 15 +- .../ui/type-alias-impl-trait/issue-60564.rs | 2 +- .../type-alias-impl-trait/issue-60564.stderr | 6 +- .../ui/type-alias-impl-trait/issue-63279.rs | 5 +- .../type-alias-impl-trait/issue-63279.stderr | 37 +- .../ui/type-alias-impl-trait/issue-63355.rs | 6 +- .../type-alias-impl-trait/issue-63355.stderr | 19 - .../issue-68368-non-defining-use-2.stderr | 4 +- .../issue-68368-non-defining-use.stderr | 4 +- .../ui/type-alias-impl-trait/issue-74280.rs | 1 + .../type-alias-impl-trait/issue-74280.stderr | 12 +- .../type-alias-impl-trait/issue-77179.stderr | 2 +- .../type-alias-impl-trait/issue-89686.stderr | 10 +- .../multiple-def-uses-in-one-fn.rs | 3 +- .../multiple-def-uses-in-one-fn.stderr | 14 +- .../multiple-def-uses-in-one-fn3.stderr | 4 +- .../nested-tait-inference.rs | 4 +- .../nested-tait-inference2.rs | 5 +- .../nested-tait-inference2.stderr | 29 +- .../nested-tait-inference3.rs | 17 + .../nested-tait-inference3.stderr | 8 + .../never_reveal_concrete_type.rs | 7 +- .../never_reveal_concrete_type.stderr | 24 - ...o_revealing_outside_defining_module.stderr | 8 +- .../not_a_defining_use.rs | 2 +- .../not_a_defining_use.stderr | 6 +- .../static-const-types.rs | 8 +- .../static-const-types.stderr | 33 -- .../structural-match-no-leak.rs | 2 +- .../type-alias-impl-trait/structural-match.rs | 2 +- .../type-alias-impl-trait-const.rs | 4 +- .../type-alias-impl-trait-const.stderr | 21 - .../type-alias-impl-trait.rs | 2 +- .../type-alias-impl-trait2.rs | 84 ++++ .../ui/type-alias-impl-trait/type_of_a_let.rs | 11 +- .../type_of_a_let.stderr | 76 +-- .../clippy_utils/src/qualify_min_const_fn.rs | 1 + 284 files changed, 2645 insertions(+), 2096 deletions(-) delete mode 100644 src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr create mode 100644 src/test/ui/impl-trait/fallback.rs create mode 100644 src/test/ui/impl-trait/issue-55872-3.rs create mode 100644 src/test/ui/impl-trait/issue-55872-3.stderr delete mode 100644 src/test/ui/impl-trait/issues/issue-70877.stderr delete mode 100644 src/test/ui/impl-trait/issues/issue-86201.stderr create mode 100644 src/test/ui/impl-trait/lifetimes2.rs create mode 100644 src/test/ui/impl-trait/question_mark.rs delete mode 100644 src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr delete mode 100644 src/test/ui/impl-trait/where-allowed-2.stderr create mode 100644 src/test/ui/lazy-type-alias-impl-trait/freeze_cycle.rs create mode 100644 src/test/ui/lazy-type-alias-impl-trait/infer_cross_function.rs create mode 100644 src/test/ui/lazy-type-alias-impl-trait/lifetime_inference.rs create mode 100644 src/test/ui/lazy-type-alias-impl-trait/nested.rs create mode 100644 src/test/ui/lazy-type-alias-impl-trait/opaque_vs_opaque.rs create mode 100644 src/test/ui/lazy-type-alias-impl-trait/unsized_sized_opaque.rs create mode 100644 src/test/ui/never_type/impl_trait_fallback.rs create mode 100644 src/test/ui/never_type/impl_trait_fallback2.rs create mode 100644 src/test/ui/never_type/impl_trait_fallback2.stderr create mode 100644 src/test/ui/never_type/impl_trait_fallback3.rs create mode 100644 src/test/ui/never_type/impl_trait_fallback3.stderr create mode 100644 src/test/ui/never_type/impl_trait_fallback4.rs create mode 100644 src/test/ui/never_type/impl_trait_fallback4.stderr delete mode 100644 src/test/ui/type-alias-impl-trait/argument-types.stderr delete mode 100644 src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr delete mode 100644 src/test/ui/type-alias-impl-trait/field-types.stderr create mode 100644 src/test/ui/type-alias-impl-trait/issue-58951-2.rs delete mode 100644 src/test/ui/type-alias-impl-trait/issue-63355.stderr create mode 100644 src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs create mode 100644 src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr delete mode 100644 src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr delete mode 100644 src/test/ui/type-alias-impl-trait/static-const-types.stderr delete mode 100644 src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr create mode 100644 src/test/ui/type-alias-impl-trait/type-alias-impl-trait2.rs diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index c288cc96990c2..09b3bc5f73739 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -124,8 +124,9 @@ fn mir_borrowck<'tcx>( ) -> &'tcx BorrowCheckResult<'tcx> { let (input_body, promoted) = tcx.mir_promoted(def); debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id())); + let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner; - let opt_closure_req = tcx.infer_ctxt().with_opaque_type_inference(def.did).enter(|infcx| { + let opt_closure_req = tcx.infer_ctxt().with_opaque_type_inference(hir_owner).enter(|infcx| { let input_body: &Body<'_> = &input_body.borrow(); let promoted: &IndexVec<_, _> = &promoted.borrow(); do_mir_borrowck(&infcx, input_body, promoted, false).0 @@ -140,7 +141,7 @@ fn mir_borrowck<'tcx>( /// If `return_body_with_facts` is true, then return the body with non-erased /// region ids on which the borrow checking was performed together with Polonius /// facts. -#[instrument(skip(infcx, input_body, input_promoted), level = "debug")] +#[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.with_opt_param().as_local().unwrap()), level = "debug")] fn do_mir_borrowck<'a, 'tcx>( infcx: &InferCtxt<'a, 'tcx>, input_body: &Body<'tcx>, diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 76b3be7976c61..205578c638acd 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -1,7 +1,6 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::vec_map::VecMap; use rustc_hir::OpaqueTyOrigin; -use rustc_infer::infer::opaque_types::OpaqueTypeDecl; use rustc_infer::infer::InferCtxt; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable}; @@ -54,27 +53,40 @@ impl<'tcx> RegionInferenceContext<'tcx> { pub(crate) fn infer_opaque_types( &self, infcx: &InferCtxt<'_, 'tcx>, - opaque_ty_decls: VecMap, OpaqueTypeDecl<'tcx>>, + opaque_ty_decls: VecMap, (Ty<'tcx>, Span, OpaqueTyOrigin)>, span: Span, ) -> VecMap, Ty<'tcx>> { opaque_ty_decls .into_iter() - .filter_map(|(opaque_type_key, decl)| { + .filter_map(|(opaque_type_key, (concrete_type, decl_span, origin))| { let substs = opaque_type_key.substs; - let concrete_type = decl.concrete_ty; + // FIXME: why are the spans in decl_span often DUMMY_SP? + let span = decl_span.substitute_dummy(span); debug!(?concrete_type, ?substs); let mut subst_regions = vec![self.universal_regions.fr_static]; let universal_substs = infcx.tcx.fold_regions(substs, &mut false, |region, _| { - let vid = self.universal_regions.to_region_vid(region); - subst_regions.push(vid); - self.definitions[vid].external_name.unwrap_or_else(|| { - infcx - .tcx - .sess - .delay_span_bug(span, "opaque type with non-universal region substs"); - infcx.tcx.lifetimes.re_static - }) + let vid = self.to_region_vid(region); + trace!(?vid); + let scc = self.constraint_sccs.scc(vid); + trace!(?scc); + match self.scc_values.universal_regions_outlived_by(scc).find_map(|lb| { + self.eval_equal(vid, lb).then_some(self.definitions[lb].external_name?) + }) { + Some(region) => { + let vid = self.universal_regions.to_region_vid(region); + subst_regions.push(vid); + region + } + None => { + subst_regions.push(vid); + infcx.tcx.sess.delay_span_bug( + span, + "opaque type with non-universal region substs", + ); + infcx.tcx.lifetimes.re_static + } + } }); subst_regions.sort(); @@ -100,12 +112,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { span, ); - check_opaque_type_parameter_valid( - infcx.tcx, - opaque_type_key, - OpaqueTypeDecl { concrete_ty: remapped_type, ..decl }, - ) - .then_some((opaque_type_key, remapped_type)) + check_opaque_type_parameter_valid(infcx.tcx, opaque_type_key, origin, span) + .then_some((opaque_type_key, remapped_type)) }) .collect() } @@ -149,9 +157,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn check_opaque_type_parameter_valid( tcx: TyCtxt<'_>, opaque_type_key: OpaqueTypeKey<'_>, - decl: OpaqueTypeDecl<'_>, + origin: OpaqueTyOrigin, + span: Span, ) -> bool { - match decl.origin { + match origin { // No need to check return position impl trait (RPIT) // because for type and const parameters they are correct // by construction: we convert @@ -177,7 +186,6 @@ fn check_opaque_type_parameter_valid( // Check these OpaqueTyOrigin::TyAlias => {} } - let span = decl.definition_span; let opaque_generics = tcx.generics_of(opaque_type_key.def_id); let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default(); for (i, arg) in opaque_type_key.substs.iter().enumerate() { diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index bc740de515065..83c8ecba1f17a 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -147,9 +147,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // Return types are a bit more complex. They may contain opaque `impl Trait` types. let mir_output_ty = body.local_decls[RETURN_PLACE].ty; let output_span = body.local_decls[RETURN_PLACE].source_info.span; - if let Err(terr) = self.eq_opaque_type_and_type( - mir_output_ty, + if let Err(terr) = self.eq_types( normalized_output_ty, + mir_output_ty, Locations::All(output_span), ConstraintCategory::BoringNoLocation, ) { @@ -169,9 +169,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let user_provided_output_ty = user_provided_sig.output(); let user_provided_output_ty = self.normalize(user_provided_output_ty, Locations::All(output_span)); - if let Err(err) = self.eq_opaque_type_and_type( - mir_output_ty, + if let Err(err) = self.eq_types( user_provided_output_ty, + mir_output_ty, Locations::All(output_span), ConstraintCategory::BoringNoLocation, ) { diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 75305d9c92311..da270be5ef0a8 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -5,6 +5,7 @@ use std::{fmt, iter, mem}; use either::Either; +use hir::OpaqueTyOrigin; use rustc_data_structures::frozen::Frozen; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::vec_map::VecMap; @@ -15,12 +16,9 @@ use rustc_hir::def_id::LocalDefId; use rustc_hir::lang_items::LangItem; use rustc_index::vec::{Idx, IndexVec}; use rustc_infer::infer::canonical::QueryRegionConstraints; -use rustc_infer::infer::opaque_types::OpaqueTypeDecl; use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::{ - InferCtxt, InferOk, LateBoundRegionConversionTime, NllRegionVariableOrigin, -}; +use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime, NllRegionVariableOrigin}; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::AssertKind; @@ -41,7 +39,7 @@ use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::query::type_op; use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; use rustc_trait_selection::traits::query::Fallible; -use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligations}; +use rustc_trait_selection::traits::{self, ObligationCause}; use rustc_const_eval::transform::{ check_consts::ConstCx, promote_consts::is_const_fn_in_array_repeat_expression, @@ -75,7 +73,7 @@ macro_rules! span_mirbug { $context.last_span, &format!( "broken MIR in {:?} ({:?}): {}", - $context.body.source.def_id(), + $context.body().source.def_id(), $elem, format_args!($($message)*), ), @@ -193,24 +191,40 @@ pub(crate) fn type_check<'mir, 'tcx>( let opaque_type_values = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); - opaque_type_values + let opaque_type_values = opaque_type_values .into_iter() - .filter_map(|(opaque_type_key, mut decl)| { - decl.concrete_ty = infcx.resolve_vars_if_possible(decl.concrete_ty); + .filter_map(|(opaque_type_key, decl)| { + let def_id = body.source.def_id().expect_local(); + let body_id = cx.tcx().hir().local_def_id_to_hir_id(def_id); + let cause = ObligationCause::misc(body.span, body_id); + let hidden = cx + .fully_perform_op( + Locations::All(body.span), + ConstraintCategory::OpaqueType, + CustomTypeOp::new( + |infcx| { + Ok(decl + .hidden_type(infcx, &cause, param_env) + .map_err(|e| e.0)?) + }, + || "opaque_type_map".to_string(), + ), + ) + .unwrap(); + let mut hidden_type = infcx.resolve_vars_if_possible(hidden.ty); trace!( "finalized opaque type {:?} to {:#?}", opaque_type_key, - decl.concrete_ty.kind() + hidden_type.kind() ); - if decl.concrete_ty.has_infer_types_or_consts() { + if hidden_type.has_infer_types_or_consts() { infcx.tcx.sess.delay_span_bug( - body.span, - &format!("could not resolve {:#?}", decl.concrete_ty.kind()), + hidden.span, + &format!("could not resolve {:#?}", hidden_type.kind()), ); - decl.concrete_ty = infcx.tcx.ty_error(); + hidden_type = infcx.tcx.ty_error(); } - let concrete_is_opaque = if let ty::Opaque(def_id, _) = decl.concrete_ty.kind() - { + let concrete_is_opaque = if let ty::Opaque(def_id, _) = hidden_type.kind() { *def_id == opaque_type_key.def_id } else { false @@ -242,10 +256,15 @@ pub(crate) fn type_check<'mir, 'tcx>( ); None } else { - Some((opaque_type_key, decl)) + Some((opaque_type_key, (hidden_type, hidden.span, decl.origin))) } }) - .collect() + .collect(); + // `hidden_type` may re-register an opaque type, so we need to clean out the + // newly re-added types. Either we got here successfully, so they are irrelevant, + // or we already errored anyway. + let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); + opaque_type_values }, ); @@ -275,7 +294,7 @@ fn type_check_internal<'a, 'tcx, R>( borrowck_context, ); let errors_reported = { - let mut verifier = TypeVerifier::new(&mut checker, body, promoted); + let mut verifier = TypeVerifier::new(&mut checker, promoted); verifier.visit_body(&body); verifier.errors_reported }; @@ -332,7 +351,6 @@ enum FieldAccessError { /// is a problem. struct TypeVerifier<'a, 'b, 'tcx> { cx: &'a mut TypeChecker<'b, 'tcx>, - body: &'b Body<'tcx>, promoted: &'b IndexVec>, last_span: Span, errors_reported: bool, @@ -468,7 +486,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { self.super_rvalue(rvalue, location); - let rval_ty = rvalue.ty(self.body, self.tcx()); + let rval_ty = rvalue.ty(self.body(), self.tcx()); self.sanitize_type(rvalue, rval_ty); } @@ -527,10 +545,13 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { fn new( cx: &'a mut TypeChecker<'b, 'tcx>, - body: &'b Body<'tcx>, promoted: &'b IndexVec>, ) -> Self { - TypeVerifier { body, promoted, cx, last_span: body.span, errors_reported: false } + TypeVerifier { promoted, last_span: cx.body.span, cx, errors_reported: false } + } + + fn body(&self) -> &Body<'tcx> { + self.cx.body } fn tcx(&self) -> TyCtxt<'tcx> { @@ -555,7 +576,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { ) -> PlaceTy<'tcx> { debug!("sanitize_place: {:?}", place); - let mut place_ty = PlaceTy::from_ty(self.body.local_decls[place.local].ty); + let mut place_ty = PlaceTy::from_ty(self.body().local_decls[place.local].ty); for elem in place.projection.iter() { if place_ty.variant_index.is_none() { @@ -600,7 +621,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { // checker on the promoted MIR, then transfer the constraints back to // the main MIR, changing the locations to the provided location. - let parent_body = mem::replace(&mut self.body, promoted_body); + let parent_body = mem::replace(&mut self.cx.body, promoted_body); // Use new sets of constraints and closure bounds so that we can // modify their locations. @@ -636,7 +657,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { self.cx.typeck_mir(promoted_body); } - self.body = parent_body; + self.cx.body = parent_body; // Merge the outlives constraints back in, at the given location. swap_constraints(self); @@ -698,7 +719,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { })) } ProjectionElem::Index(i) => { - let index_ty = Place::from(i).ty(self.body, tcx).ty; + let index_ty = Place::from(i).ty(self.body(), tcx).ty; if index_ty != tcx.types.usize { PlaceTy::from_ty(span_mirbug_and_err!(self, i, "index by non-usize {:?}", i)) } else { @@ -907,7 +928,7 @@ struct BorrowCheckContext<'a, 'tcx> { crate struct MirTypeckResults<'tcx> { crate constraints: MirTypeckRegionConstraints<'tcx>, crate universal_region_relations: Frozen>, - crate opaque_type_values: VecMap, OpaqueTypeDecl<'tcx>>, + crate opaque_type_values: VecMap, (Ty<'tcx>, Span, OpaqueTyOrigin)>, } /// A collection of region constraints that must be satisfied for the @@ -1057,17 +1078,19 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { checker } + fn body(&self) -> &Body<'tcx> { + self.body + } + fn unsized_feature_enabled(&self) -> bool { let features = self.tcx().features(); features.unsized_locals || features.unsized_fn_params } /// Equate the inferred type and the annotated type for user type annotations + #[instrument(skip(self), level = "debug")] fn check_user_type_annotations(&mut self) { - debug!( - "check_user_type_annotations: user_type_annotations={:?}", - self.user_type_annotations - ); + debug!(?self.user_type_annotations); for user_annotation in self.user_type_annotations { let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation; let inferred_ty = self.normalize(inferred_ty, Locations::All(span)); @@ -1208,130 +1231,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Ok(()) } - /// Equates a type `anon_ty` that may contain opaque types whose - /// values are to be inferred by the MIR. - /// - /// The type `revealed_ty` contains the same type as `anon_ty`, but with the - /// hidden types for impl traits revealed. - /// - /// # Example - /// - /// Consider a piece of code like - /// - /// ```rust - /// type Foo = impl Debug; - /// - /// fn foo(t: T) -> Box> { - /// Box::new((t, 22_u32)) - /// } - /// ``` - /// - /// Here, the function signature would be something like - /// `fn(T) -> Box`. The MIR return slot would have - /// the type with the opaque type revealed, so `Box<(T, u32)>`. - /// - /// In terms of our function parameters: - /// - /// * `anon_ty` would be `Box>` where `Foo` is an opaque type - /// scoped to this function (note that it is parameterized by the - /// generics of `foo`). Note that `anon_ty` is not just the opaque type, - /// but the entire return type (which may contain opaque types within it). - /// * `revealed_ty` would be `Box<(T, u32)>` - #[instrument(skip(self), level = "debug")] - fn eq_opaque_type_and_type( - &mut self, - revealed_ty: Ty<'tcx>, - anon_ty: Ty<'tcx>, - locations: Locations, - category: ConstraintCategory, - ) -> Fallible<()> { - // Fast path for the common case. - if !anon_ty.has_opaque_types() { - if let Err(terr) = self.eq_types(anon_ty, revealed_ty, locations, category) { - span_mirbug!( - self, - locations, - "eq_opaque_type_and_type: `{:?}=={:?}` failed with `{:?}`", - revealed_ty, - anon_ty, - terr - ); - } - return Ok(()); - } - - let param_env = self.param_env; - let body = self.body; - let mir_def_id = body.source.def_id().expect_local(); - - debug!(?mir_def_id); - self.fully_perform_op( - locations, - category, - CustomTypeOp::new( - |infcx| { - let mut obligations = ObligationAccumulator::default(); - - let dummy_body_id = hir::CRATE_HIR_ID; - - // Replace the opaque types defined by this function with - // inference variables, creating a map. In our example above, - // this would transform the type `Box>` (where `Foo` is an opaque type) - // 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 = obligations.add(infcx.instantiate_opaque_types( - dummy_body_id, - param_env, - anon_ty, - locations.span(body), - )); - debug!(?output_ty, ?revealed_ty); - - // Make sure that the inferred types are well-formed. I'm - // not entirely sure this is needed (the HIR type check - // didn't do this) but it seems sensible to prevent opaque - // types hiding ill-formed types. - obligations.obligations.push(traits::Obligation::new( - ObligationCause::dummy(), - param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(revealed_ty.into())) - .to_predicate(infcx.tcx), - )); - obligations.add( - infcx - .at(&ObligationCause::dummy(), param_env) - .eq(output_ty, revealed_ty)?, - ); - - debug!("equated"); - - Ok(InferOk { value: (), obligations: obligations.into_vec() }) - }, - || "input_output".to_string(), - ), - )?; - - // 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). - for (opaque_type_key, opaque_decl) in self.infcx.opaque_types() { - self.fully_perform_op( - locations, - ConstraintCategory::OpaqueType, - CustomTypeOp::new( - |infcx| { - infcx.constrain_opaque_type(opaque_type_key, &opaque_decl); - Ok(InferOk { value: (), obligations: vec![] }) - }, - || "opaque_type_map".to_string(), - ), - )?; - } - Ok(()) - } - fn tcx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -1881,6 +1780,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { fn ensure_place_sized(&mut self, ty: Ty<'tcx>, span: Span) { let tcx = self.tcx(); + // This may contain opaque types, resolve them to the underlying + // type if defined in the current function. Otherwise we can't + // necessarily prove sizedness of the type. + let ty = self.infcx.resolve_vars_if_possible(ty); + // Erase the regions from `ty` to get a global type. The // `Sized` bound in no way depends on precise regions, so this // shouldn't affect `is_sized`. @@ -2773,20 +2677,3 @@ impl NormalizeLocation for Location { Locations::Single(self) } } - -#[derive(Debug, Default)] -struct ObligationAccumulator<'tcx> { - obligations: PredicateObligations<'tcx>, -} - -impl<'tcx> ObligationAccumulator<'tcx> { - fn add(&mut self, value: InferOk<'tcx, T>) -> T { - let InferOk { value, obligations } = value; - self.obligations.extend(obligations); - value - } - - fn into_vec(self) -> PredicateObligations<'tcx> { - self.obligations - } -} diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 18d880b8de314..ccf8b44206aa8 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -1,14 +1,15 @@ use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; use rustc_infer::infer::NllRegionVariableOrigin; +use rustc_infer::traits::ObligationCause; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::{self, Const, Ty}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::Span; use rustc_trait_selection::traits::query::Fallible; use crate::constraints::OutlivesConstraint; use crate::diagnostics::UniverseInfo; -use crate::type_check::{Locations, TypeChecker}; +use crate::type_check::{CustomTypeOp, Locations, TypeChecker}; impl<'a, 'tcx> TypeChecker<'a, 'tcx> { /// Adds sufficient constraints to ensure that `a R b` where `R` depends on `v`: @@ -65,10 +66,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { fn span(&self) -> Span { - match self.locations { - Locations::All(span) => span, - Locations::Single(_) => DUMMY_SP, - } + self.locations.span(self.type_checker.body) } fn param_env(&self) -> ty::ParamEnv<'tcx> { @@ -137,4 +135,54 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> fn forbid_inference_vars() -> bool { true } + + fn constrain_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool) { + let param_env = self.param_env(); + let span = self.span(); + let def_id = self.type_checker.body.source.def_id().expect_local(); + let body_id = self.type_checker.tcx().hir().local_def_id_to_hir_id(def_id); + let cause = ObligationCause::misc(span, body_id); + self.type_checker + .fully_perform_op( + self.locations, + self.category, + CustomTypeOp::new( + |infcx| { + let (concrete_ty, opaque_type_key) = + match (a.kind(), b.kind(), a_is_expected) { + (ty::Opaque(..), ty::Opaque(..), true) => { + (b, a.expect_opaque_type()) + } + (ty::Opaque(..), ty::Opaque(..), false) => { + (a, b.expect_opaque_type()) + } + (ty::Opaque(..), _, _) => (b, a.expect_opaque_type()), + (_, ty::Opaque(..), _) => (a, b.expect_opaque_type()), + _ => span_bug!( + span, + "no opaque types in constrain_opaque_type {:?}, {:?}", + a, + b + ), + }; + let mut result = self.type_checker.infcx.constrain_opaque_type( + param_env, + opaque_type_key, + concrete_ty, + span, + )?; + result.obligations.push(infcx.opaque_ty_obligation( + a, + b, + a_is_expected, + param_env, + cause, + )); + Ok(result) + }, + || "constrain_opaque_type".to_string(), + ), + ) + .unwrap(); + } } diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 16a903d5e593f..a944b2d87ac6d 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -728,6 +728,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { self.tcx.fold_regions(value, &mut false, |_region, _depth| self.next_nll_region_var(origin)) } + #[instrument(level = "debug", skip(self, indices))] fn replace_bound_regions_with_nll_infer_vars( &self, origin: NllRegionVariableOrigin, @@ -738,22 +739,15 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { where T: TypeFoldable<'tcx>, { - debug!( - "replace_bound_regions_with_nll_infer_vars(value={:?}, all_outlive_scope={:?})", - value, all_outlive_scope, - ); let (value, _map) = self.tcx.replace_late_bound_regions(value, |br| { - debug!("replace_bound_regions_with_nll_infer_vars: br={:?}", br); + debug!(?br); let liberated_region = self.tcx.mk_region(ty::ReFree(ty::FreeRegion { scope: all_outlive_scope.to_def_id(), bound_region: br.kind, })); let region_vid = self.next_nll_region_var(origin); indices.insert_late_bound_region(liberated_region, region_vid.to_region_vid()); - debug!( - "replace_bound_regions_with_nll_infer_vars: liberated_region={:?} => {:?}", - liberated_region, region_vid - ); + debug!(?liberated_region, ?region_vid); region_vid }); value @@ -768,6 +762,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { /// entries for them and store them in the indices map. This code iterates over the complete /// set of late-bound regions and checks for any that we have not yet seen, adding them to the /// inputs vector. + #[instrument(skip(self, indices))] fn replace_late_bound_regions_with_nll_infer_vars( &self, mir_def_id: LocalDefId, @@ -779,6 +774,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { debug!("replace_late_bound_regions_with_nll_infer_vars: r={:?}", r); if !indices.indices.contains_key(&r) { let region_vid = self.next_nll_region_var(FR); + debug!(?region_vid); indices.insert_late_bound_region(r, region_vid.to_region_vid()); } }); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 6799514a4490d..e2dbeef35b9d3 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -11,7 +11,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::cast::CastTy; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt}; -use rustc_middle::ty::{Binder, TraitPredicate, TraitRef}; +use rustc_middle::ty::{Binder, TraitPredicate, TraitRef, TypeFoldable}; use rustc_mir_dataflow::{self, Analysis}; use rustc_span::{sym, Span, Symbol}; use rustc_trait_selection::traits::SelectionContext; @@ -46,7 +46,10 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { location: Location, ) -> bool { let ty = ccx.body.local_decls[local].ty; - if !NeedsDrop::in_any_value_of_ty(ccx, ty) { + // Peeking into opaque types causes cycles if the current function declares said opaque + // type. Thus we avoid short circuiting on the type and instead run the more expensive + // analysis that looks at the actual usage withhin this function + if !ty.has_opaque_types() && !NeedsDrop::in_any_value_of_ty(ccx, ty) { return false; } @@ -100,7 +103,10 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { location: Location, ) -> bool { let ty = ccx.body.local_decls[local].ty; - if !HasMutInterior::in_any_value_of_ty(ccx, ty) { + // Peeking into opaque types causes cycles if the current function declares said opaque + // type. Thus we avoid short circuiting on the type and instead run the more expensive + // analysis that looks at the actual usage withhin this function + if !ty.has_opaque_types() && !HasMutInterior::in_any_value_of_ty(ccx, ty) { return false; } @@ -148,7 +154,12 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { // If we know that all values of the return type are structurally matchable, there's no // need to run dataflow. - _ if !CustomEq::in_any_value_of_ty(ccx, ccx.body.return_ty()) => false, + // Opaque types do not participate in const generics or pattern matching, so we can safely count them out. + _ if ccx.body.return_ty().has_opaque_types() + || !CustomEq::in_any_value_of_ty(ccx, ccx.body.return_ty()) => + { + false + } hir::ConstContext::Const | hir::ConstContext::Static(_) => { let mut cursor = FlowSensitiveAnalysis::new(CustomEq, ccx) @@ -395,6 +406,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { | ty::PredicateKind::Projection(_) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue, ty::PredicateKind::ObjectSafe(_) => { bug!("object safe predicate on function: {:#?}", predicate) diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 22ef0b2dda506..4aeb6adfe4571 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -78,7 +78,6 @@ pub fn equal_up_to_regions<'tcx>( } // Normalize lifetimes away on both sides, then compare. - let param_env = param_env.with_reveal_all_normalized(tcx); let normalize = |ty: Ty<'tcx>| { tcx.normalize_erasing_regions( param_env, @@ -169,9 +168,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { return true; } // Normalize projections and things like that. - // FIXME: We need to reveal_all, as some optimizations change types in ways - // that require unfolding opaque types. - let param_env = self.param_env.with_reveal_all_normalized(self.tcx); + let param_env = self.param_env; let src = self.tcx.normalize_erasing_regions(param_env, src); let dest = self.tcx.normalize_erasing_regions(param_env, dest); diff --git a/compiler/rustc_data_structures/src/vec_map.rs b/compiler/rustc_data_structures/src/vec_map.rs index 8f525230e7eec..2f4b3844430e3 100644 --- a/compiler/rustc_data_structures/src/vec_map.rs +++ b/compiler/rustc_data_structures/src/vec_map.rs @@ -44,6 +44,15 @@ where self.0.iter().find(|(key, _)| k == key.borrow()).map(|elem| &elem.1) } + /// Gets a mutable reference to the value in the entry. + pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> + where + K: Borrow, + Q: Eq, + { + self.0.iter_mut().find(|(key, _)| k == key.borrow()).map(|elem| &mut elem.1) + } + /// Returns the any value corresponding to the supplied predicate filter. /// /// The supplied predicate will be applied to each (key, value) pair and it will return a @@ -63,7 +72,7 @@ where // This should return just one element, otherwise it's a bug assert!( filter.next().is_none(), - "Collection {:?} should have just one matching element", + "Collection {:#?} should have just one matching element", self ); Some(value) diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 147061dafeb1e..7a82b169c5720 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -34,6 +34,12 @@ pub struct At<'a, 'tcx> { pub infcx: &'a InferCtxt<'a, 'tcx>, pub cause: &'a ObligationCause<'tcx>, pub param_env: ty::ParamEnv<'tcx>, + /// Whether we should define opaque types + /// or just treat them opaquely. + /// Currently only used to prevent predicate + /// matching from matching anything against opaque + /// types. + pub define_opaque_types: bool, } pub struct Trace<'a, 'tcx> { @@ -49,7 +55,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { cause: &'a ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> At<'a, 'tcx> { - At { infcx: self, cause, param_env } + At { infcx: self, cause, param_env, define_opaque_types: true } } } @@ -64,6 +70,10 @@ pub trait ToTrace<'tcx>: Relate<'tcx> + Copy { } impl<'a, 'tcx> At<'a, 'tcx> { + pub fn define_opaque_types(self, define_opaque_types: bool) -> Self { + Self { define_opaque_types, ..self } + } + /// Hacky routine for equating two impl headers in coherence. pub fn eq_impl_headers( self, @@ -194,7 +204,7 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { { let Trace { at, trace, a_is_expected } = self; at.infcx.commit_if_ok(|_| { - let mut fields = at.infcx.combine_fields(trace, at.param_env); + let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types); fields .sub(a_is_expected) .relate(a, b) @@ -211,7 +221,7 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { { let Trace { at, trace, a_is_expected } = self; at.infcx.commit_if_ok(|_| { - let mut fields = at.infcx.combine_fields(trace, at.param_env); + let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types); fields .equate(a_is_expected) .relate(a, b) @@ -226,7 +236,7 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { { let Trace { at, trace, a_is_expected } = self; at.infcx.commit_if_ok(|_| { - let mut fields = at.infcx.combine_fields(trace, at.param_env); + let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types); fields .lub(a_is_expected) .relate(a, b) @@ -241,7 +251,7 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { { let Trace { at, trace, a_is_expected } = self; at.infcx.commit_if_ok(|_| { - let mut fields = at.infcx.combine_fields(trace, at.param_env); + let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types); fields .glb(a_is_expected) .relate(a, b) diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index fd41114d57561..ecb50dd60973f 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -25,7 +25,7 @@ use rustc_middle::arena::ArenaAllocatable; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; -use rustc_middle::ty::{self, BoundVar, Const, ToPredicate, Ty, TyCtxt}; +use rustc_middle::ty::{self, BoundVar, Const, OpaqueTypeKey, ToPredicate, Ty, TyCtxt}; use rustc_span::Span; use std::fmt::Debug; use std::iter; @@ -90,6 +90,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { var_values: inference_vars, region_constraints: QueryRegionConstraints::default(), certainty: Certainty::Proven, // Ambiguities are OK! + opaque_types: vec![], value: answer, }) } @@ -134,14 +135,27 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let certainty = if ambig_errors.is_empty() { Certainty::Proven } else { Certainty::Ambiguous }; + let opaque_types = self.take_opaque_types_for_query_response(); + Ok(QueryResponse { var_values: inference_vars, region_constraints, certainty, value: answer, + opaque_types, }) } + fn take_opaque_types_for_query_response(&self) -> Vec<(OpaqueTypeKey<'tcx>, Vec>)> { + self.inner + .borrow_mut() + .opaque_type_storage + .take_opaque_types() + .into_iter() + .map(|(k, v)| (k, v.hidden_types.into_iter().map(|ht| ht.ty).collect())) + .collect() + } + /// Given the (canonicalized) result to a canonical query, /// instantiates the result so it can be used, plugging in the /// values from the canonical query. (Note that the result may @@ -224,13 +238,12 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { where R: Debug + TypeFoldable<'tcx>, { - let result_subst = - self.query_response_substitution_guess(cause, original_values, query_response); + let InferOk { value: result_subst, mut obligations } = self + .query_response_substitution_guess(cause, param_env, original_values, query_response)?; // Compute `QueryOutlivesConstraint` values that unify each of // the original values `v_o` that was canonicalized into a // variable... - let mut obligations = vec![]; for (index, original_value) in original_values.var_values.iter().enumerate() { // ...with the value `v_r` of that variable from the query. @@ -345,20 +358,25 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { original_values, query_response, ); - let result_subst = - self.query_response_substitution_guess(cause, original_values, query_response); + let mut value = self.query_response_substitution_guess( + cause, + param_env, + original_values, + query_response, + )?; - let obligations = self - .unify_query_response_substitution_guess( + value.obligations.extend( + self.unify_query_response_substitution_guess( cause, param_env, original_values, - &result_subst, + &value.value, query_response, )? - .into_obligations(); + .into_obligations(), + ); - Ok(InferOk { value: result_subst, obligations }) + Ok(value) } /// Given the original values and the (canonicalized) result from @@ -373,9 +391,10 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { fn query_response_substitution_guess( &self, cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, original_values: &OriginalQueryValues<'tcx>, query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>, - ) -> CanonicalVarValues<'tcx> + ) -> InferResult<'tcx, CanonicalVarValues<'tcx>> where R: Debug + TypeFoldable<'tcx>, { @@ -475,7 +494,19 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { .collect(), }; - result_subst + let mut obligations = vec![]; + + // Carry all newly resolved opaque types to the caller's scope + for (key, tys) in &query_response.value.opaque_types { + let substs = substitute_value(self.tcx, &result_subst, key.substs); + let opaque = self.tcx.mk_opaque(key.def_id, substs); + for &ty in tys { + let ty = substitute_value(self.tcx, &result_subst, ty); + obligations.extend(self.handle_opaque_type(opaque, ty, cause, param_env)?); + } + } + + Ok(InferOk { value: result_subst, obligations }) } /// Given a "guess" at the values for the canonical variables in @@ -691,4 +722,14 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> { fn forbid_inference_vars() -> bool { true } + + fn constrain_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool) { + self.obligations.push(self.infcx.opaque_ty_obligation( + a, + b, + a_is_expected, + self.param_env, + self.cause.clone(), + )); + } } diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index a77fd8fae8d20..5668b6c10b000 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -51,6 +51,12 @@ pub struct CombineFields<'infcx, 'tcx> { pub cause: Option, pub param_env: ty::ParamEnv<'tcx>, pub obligations: PredicateObligations<'tcx>, + /// Whether we should define opaque types + /// or just treat them opaquely. + /// Currently only used to prevent predicate + /// matching from matching anything against opaque + /// types. + pub define_opaque_types: bool, } #[derive(Copy, Clone, Debug)] @@ -322,6 +328,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { /// will first instantiate `b_vid` with a *generalized* version /// of `a_ty`. Generalization introduces other inference /// variables wherever subtyping could occur. + #[instrument(skip(self), level = "debug")] pub fn instantiate( &mut self, a_ty: Ty<'tcx>, @@ -334,8 +341,6 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { // Get the actual variable that b_vid has been inferred to debug_assert!(self.infcx.inner.borrow_mut().type_variables().probe(b_vid).is_unknown()); - debug!("instantiate(a_ty={:?} dir={:?} b_vid={:?})", a_ty, dir, b_vid); - // Generalize type of `a_ty` appropriately depending on the // direction. As an example, assume: // @@ -348,10 +353,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { // variables. (Down below, we will relate `a_ty <: b_ty`, // adding constraints like `'x: '?2` and `?1 <: ?3`.) let Generalization { ty: b_ty, needs_wf } = self.generalize(a_ty, b_vid, dir)?; - debug!( - "instantiate(a_ty={:?}, dir={:?}, b_vid={:?}, generalized b_ty={:?})", - a_ty, dir, b_vid, b_ty - ); + debug!(?b_ty); self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty); if needs_wf { @@ -392,13 +394,13 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { /// Preconditions: /// /// - `for_vid` is a "root vid" + #[instrument(skip(self), level = "trace")] fn generalize( &self, ty: Ty<'tcx>, for_vid: ty::TyVid, dir: RelationDir, ) -> RelateResult<'tcx, Generalization<'tcx>> { - debug!("generalize(ty={:?}, for_vid={:?}, dir={:?}", ty, for_vid, dir); // Determine the ambient variance within which `ty` appears. // The surrounding equation is: // @@ -412,7 +414,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { RelationDir::SupertypeOf => ty::Contravariant, }; - debug!("generalize: ambient_variance = {:?}", ambient_variance); + trace!(?ambient_variance); let for_universe = match self.infcx.inner.borrow_mut().type_variables().probe(for_vid) { v @ TypeVariableValue::Known { .. } => { @@ -421,8 +423,8 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { TypeVariableValue::Unknown { universe } => universe, }; - debug!("generalize: for_universe = {:?}", for_universe); - debug!("generalize: trace = {:?}", self.trace); + trace!(?for_universe); + trace!(?self.trace); let mut generalize = Generalizer { infcx: self.infcx, @@ -439,12 +441,12 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { let ty = match generalize.relate(ty, ty) { Ok(ty) => ty, Err(e) => { - debug!("generalize: failure {:?}", e); + debug!(?e, "failure"); return Err(e); } }; let needs_wf = generalize.needs_wf; - debug!("generalize: success {{ {:?}, {:?} }}", ty, needs_wf); + trace!(?ty, ?needs_wf, "success"); Ok(Generalization { ty, needs_wf }) } diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index 06692be4f7265..9f6c6d3184533 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -75,9 +75,9 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> { trace!(a = ?a.kind(), b = ?b.kind()); let infcx = self.fields.infcx; + let a = infcx.inner.borrow_mut().type_variables().replace_if_possible(a); let b = infcx.inner.borrow_mut().type_variables().replace_if_possible(b); - trace!(a = ?a.kind(), b = ?b.kind(), "replacements"); match (a.kind(), b.kind()) { (&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => { @@ -92,6 +92,21 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> { self.fields.instantiate(a, RelationDir::EqTo, b_id, self.a_is_expected)?; } + (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => { + self.fields.infcx.super_combine_tys(self, a, b)?; + } + (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..)) + if self.fields.define_opaque_types && did.is_local() => + { + self.fields.obligations.push(infcx.opaque_ty_obligation( + a, + b, + self.a_is_expected(), + self.param_env(), + self.fields.trace.cause.clone(), + )); + } + _ => { self.fields.infcx.super_combine_tys(self, a, b)?; } diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 4af1bdf97a773..d159c14b1cfb7 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -214,8 +214,8 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { | ty::Foreign(..) | ty::Param(..) | ty::Closure(..) - | ty::GeneratorWitness(..) - | ty::Opaque(..) => t.super_fold_with(self), + | ty::Opaque(..) + | ty::GeneratorWitness(..) => t.super_fold_with(self), ty::Placeholder(..) | ty::Bound(..) => bug!("unexpected type {:?}", t), } diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs index 862f5a5fbb8c1..c4c4eab261e86 100644 --- a/compiler/rustc_infer/src/infer/glb.rs +++ b/compiler/rustc_infer/src/infer/glb.rs @@ -4,7 +4,7 @@ use super::InferCtxt; use super::Subtype; use crate::infer::combine::ConstEquateRelation; -use crate::traits::ObligationCause; +use crate::traits::{ObligationCause, PredicateObligation}; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -111,12 +111,20 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx, &self.fields.trace.cause } + fn add_obligations(&mut self, obligations: Vec>) { + self.fields.obligations.extend(obligations) + } + fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> { let mut sub = self.fields.sub(self.a_is_expected); sub.relate(v, a)?; sub.relate(v, b)?; Ok(()) } + + fn define_opaque_types(&self) -> bool { + self.fields.define_opaque_types + } } impl<'tcx> ConstEquateRelation<'tcx> for Glb<'_, '_, 'tcx> { diff --git a/compiler/rustc_infer/src/infer/lattice.rs b/compiler/rustc_infer/src/infer/lattice.rs index c47d476963772..6bda44f0ef256 100644 --- a/compiler/rustc_infer/src/infer/lattice.rs +++ b/compiler/rustc_infer/src/infer/lattice.rs @@ -22,7 +22,7 @@ use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use super::InferCtxt; -use crate::traits::ObligationCause; +use crate::traits::{ObligationCause, PredicateObligation}; use rustc_middle::ty::relate::{RelateResult, TypeRelation}; use rustc_middle::ty::TyVar; use rustc_middle::ty::{self, Ty}; @@ -32,6 +32,10 @@ pub trait LatticeDir<'f, 'tcx>: TypeRelation<'tcx> { fn cause(&self) -> &ObligationCause<'tcx>; + fn add_obligations(&mut self, obligations: Vec>); + + fn define_opaque_types(&self) -> bool; + // Relates the type `v` to `a` and `b` such that `v` represents // the LUB/GLB of `a` and `b` as appropriate. // @@ -41,6 +45,7 @@ pub trait LatticeDir<'f, 'tcx>: TypeRelation<'tcx> { fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>; } +#[instrument(skip(this), level = "debug")] pub fn super_lattice_tys<'a, 'tcx: 'a, L>( this: &mut L, a: Ty<'tcx>, @@ -49,15 +54,17 @@ pub fn super_lattice_tys<'a, 'tcx: 'a, L>( where L: LatticeDir<'a, 'tcx>, { - debug!("{}.lattice_tys({:?}, {:?})", this.tag(), a, b); + debug!("{}", this.tag()); if a == b { return Ok(a); } let infcx = this.infcx(); + let a = infcx.inner.borrow_mut().type_variables().replace_if_possible(a); let b = infcx.inner.borrow_mut().type_variables().replace_if_possible(b); + match (a.kind(), b.kind()) { // If one side is known to be a variable and one is not, // create a variable (`v`) to represent the LUB. Make sure to @@ -94,6 +101,22 @@ where Ok(v) } + (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => { + infcx.super_combine_tys(this, a, b) + } + (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..)) + if this.define_opaque_types() && did.is_local() => + { + this.add_obligations(vec![infcx.opaque_ty_obligation( + a, + b, + this.a_is_expected(), + this.param_env(), + this.cause().clone(), + )]); + Ok(a) + } + _ => infcx.super_combine_tys(this, a, b), } } diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs index 5191d1c1cc100..bbd8e00146905 100644 --- a/compiler/rustc_infer/src/infer/lub.rs +++ b/compiler/rustc_infer/src/infer/lub.rs @@ -4,7 +4,7 @@ use super::InferCtxt; use super::Subtype; use crate::infer::combine::ConstEquateRelation; -use crate::traits::ObligationCause; +use crate::traits::{ObligationCause, PredicateObligation}; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -117,10 +117,18 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx, &self.fields.trace.cause } + fn add_obligations(&mut self, obligations: Vec>) { + self.fields.obligations.extend(obligations) + } + fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> { let mut sub = self.fields.sub(self.a_is_expected); sub.relate(a, v)?; sub.relate(b, v)?; Ok(()) } + + fn define_opaque_types(&self) -> bool { + self.fields.define_opaque_types + } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 6c7e079a724a5..15ce690479b1a 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -227,7 +227,7 @@ impl<'tcx> InferCtxtInner<'tcx> { } #[inline] - fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'tcx> { + pub fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'tcx> { self.opaque_type_storage.with_log(&mut self.undo_log) } @@ -291,6 +291,10 @@ pub struct InferCtxt<'a, 'tcx> { /// to the outside until the end up in an `InferCtxt` for typeck or borrowck. pub defining_use_anchor: Option, + /// Used by WF-checking to not have to figure out hidden types itself, but + /// to just invoke type_of to get the already computed hidden type from typeck. + pub reveal_defining_opaque_types: bool, + /// 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, @@ -546,6 +550,7 @@ pub struct InferCtxtBuilder<'tcx> { tcx: TyCtxt<'tcx>, fresh_typeck_results: Option>>, defining_use_anchor: Option, + reveal_defining_opaque_types: bool, } pub trait TyCtxtInferExt<'tcx> { @@ -554,7 +559,12 @@ pub trait TyCtxtInferExt<'tcx> { impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> { fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> { - InferCtxtBuilder { tcx: self, defining_use_anchor: None, fresh_typeck_results: None } + InferCtxtBuilder { + tcx: self, + defining_use_anchor: None, + fresh_typeck_results: None, + reveal_defining_opaque_types: false, + } } } @@ -578,6 +588,13 @@ impl<'tcx> InferCtxtBuilder<'tcx> { self } + /// WF-checking doesn't need to recompute opaque types and can instead use + /// the type_of query to get them from typeck. + pub fn reveal_defining_opaque_types(mut self) -> Self { + self.reveal_defining_opaque_types = true; + self + } + /// Given a canonical value `C` as a starting point, create an /// inference context that contains each of the bound values /// within instantiated as a fresh variable. The `f` closure is @@ -602,11 +619,17 @@ impl<'tcx> InferCtxtBuilder<'tcx> { } pub fn enter(&mut self, f: impl for<'a> FnOnce(InferCtxt<'a, 'tcx>) -> R) -> R { - let InferCtxtBuilder { tcx, defining_use_anchor, ref fresh_typeck_results } = *self; + let InferCtxtBuilder { + tcx, + defining_use_anchor, + reveal_defining_opaque_types, + ref fresh_typeck_results, + } = *self; let in_progress_typeck_results = fresh_typeck_results.as_ref(); f(InferCtxt { tcx, defining_use_anchor, + reveal_defining_opaque_types, in_progress_typeck_results, inner: RefCell::new(InferCtxtInner::new()), lexical_region_resolutions: RefCell::new(None), @@ -728,6 +751,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &'a self, trace: TypeTrace<'tcx>, param_env: ty::ParamEnv<'tcx>, + define_opaque_types: bool, ) -> CombineFields<'a, 'tcx> { CombineFields { infcx: self, @@ -735,6 +759,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { cause: None, param_env, obligations: PredicateObligations::new(), + define_opaque_types, } } @@ -1050,12 +1075,20 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.mk_ty_var(self.next_ty_var_id(origin)) } + pub fn next_ty_var_id_in_universe( + &self, + origin: TypeVariableOrigin, + universe: ty::UniverseIndex, + ) -> TyVid { + self.inner.borrow_mut().type_variables().new_var(universe, origin) + } + pub fn next_ty_var_in_universe( &self, origin: TypeVariableOrigin, universe: ty::UniverseIndex, ) -> Ty<'tcx> { - let vid = self.inner.borrow_mut().type_variables().new_var(universe, origin); + let vid = self.next_ty_var_id_in_universe(origin, universe); self.tcx.mk_ty_var(vid) } diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 95de2d40bb9c9..5f4555a78f311 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -24,6 +24,7 @@ use crate::infer::combine::ConstEquateRelation; use crate::infer::InferCtxt; use crate::infer::{ConstVarValue, ConstVariableValue}; +use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::fold::{TypeFoldable, TypeVisitor}; @@ -89,6 +90,8 @@ pub trait TypeRelatingDelegate<'tcx> { info: ty::VarianceDiagInfo<'tcx>, ); + fn constrain_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool); + fn const_equate(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>); /// Creates a new universe index. Used when instantiating placeholders. @@ -279,7 +282,6 @@ where projection_ty: ty::ProjectionTy<'tcx>, value_ty: Ty<'tcx>, ) -> Ty<'tcx> { - use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_span::DUMMY_SP; match *value_ty.kind() { @@ -288,6 +290,8 @@ where kind: TypeVariableOriginKind::MiscVariable, span: DUMMY_SP, }); + // FIXME(lazy-normalization): This will always ICE, because the recursive + // call will end up in the _ arm below. self.relate_projection_ty(projection_ty, var); self.relate_projection_ty(other_projection_ty, var); var @@ -533,6 +537,8 @@ where #[instrument(skip(self), level = "debug")] fn tys(&mut self, a: Ty<'tcx>, mut b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + let infcx = self.infcx; + let a = self.infcx.shallow_resolve(a); if !D::forbid_inference_vars() { @@ -561,6 +567,35 @@ where (&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)), + (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => { + self.infcx.super_combine_tys(self, a, b) + } + (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..)) if did.is_local() => { + let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) }; + let mut generalize = |ty, ty_is_expected| { + let var = infcx.next_ty_var_id_in_universe( + TypeVariableOrigin { + kind: TypeVariableOriginKind::MiscVariable, + span: self.delegate.span(), + }, + ty::UniverseIndex::ROOT, + ); + if ty_is_expected { + self.relate_ty_var((ty, var)) + } else { + self.relate_ty_var((var, ty)) + } + }; + let (a, b) = match (a.kind(), b.kind()) { + (&ty::Opaque(..), _) => (a, generalize(b, false)?), + (_, &ty::Opaque(..)) => (generalize(a, true)?, b), + _ => unreachable!(), + }; + self.delegate.constrain_opaque_type(a, b, true); + trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated"); + Ok(a) + } + (&ty::Projection(projection_ty), _) if D::normalization() == NormalizationStrategy::Lazy => { diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index e3e48a7f890e5..3ba4b9427251c 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -1,10 +1,13 @@ use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use crate::infer::{InferCtxt, InferOk}; -use crate::traits; +use crate::infer::{InferCtxt, InferOk, InferResult}; +use crate::traits::{self, PredicateObligation, PredicateObligations}; +use hir::def_id::{DefId, LocalDefId}; +use hir::OpaqueTyOrigin; use rustc_data_structures::sync::Lrc; use rustc_data_structures::vec_map::VecMap; use rustc_hir as hir; -use rustc_hir::def_id::LocalDefId; +use rustc_middle::traits::ObligationCause; +use rustc_middle::ty::error::TypeError; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::subst::{GenericArgKind, Subst}; use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitor}; @@ -21,11 +24,71 @@ pub use table::{OpaqueTypeStorage, OpaqueTypeTable}; /// 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)] +#[derive(Clone, Debug)] pub struct OpaqueTypeDecl<'tcx> { /// The opaque type (`ty::Opaque`) for this declaration. pub opaque_type: Ty<'tcx>, + /// The hidden types that have been inferred for this opaque type. + /// There can be multiple, but they are all `lub`ed together at the end + /// to obtain the canonical hidden type. + pub hidden_types: Vec>, + + /// The origin of the opaque type. + pub origin: hir::OpaqueTyOrigin, +} + +impl<'tcx> OpaqueTypeDecl<'tcx> { + pub fn hidden_type( + &self, + infcx: &InferCtxt<'_, 'tcx>, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> Result< + InferOk<'tcx, OpaqueHiddenType<'tcx>>, + (TypeError<'tcx>, OpaqueHiddenType<'tcx>, OpaqueHiddenType<'tcx>), + > { + let mut value = self.hidden_types[0]; + let mut obligations = vec![]; + let mut error: Option<(_, _, OpaqueHiddenType<'tcx>)> = None; + for &next in self.hidden_types[1..].iter() { + // FIXME: make use of the spans to get nicer diagnostics! + let res = match infcx.at(cause, param_env).eq(value.ty, next.ty) { + Ok(res) => res, + Err(e) => { + // Try to improve the span. Sometimes we have dummy spans, sometimes we are pointing + // at an if/match instead of at the arm that gave us the type, but later spans point + // to the right thing. + if let Some((_, _, old)) = &mut error { + old.span = old.span.substitute_dummy(next.span); + // Shrink the span if possible + if old.span.contains(next.span) { + old.span = next.span; + } + } else { + let mut next = next; + next.span = next.span.substitute_dummy(cause.span(infcx.tcx)); + error = Some((e, value, next)); + } + continue; + } + }; + obligations.extend(res.obligations); + value.span = value.span.substitute_dummy(next.span); + // Shrink the span if possible + if value.span.contains(next.span) { + value.span = next.span; + } + } + match error { + None => Ok(InferOk { value, obligations }), + Some(e) => Err(e), + } + } +} + +#[derive(Copy, Clone, Debug, TypeFoldable)] +pub struct OpaqueHiddenType<'tcx> { /// The span of this particular definition of the opaque type. So /// for example: /// @@ -39,7 +102,7 @@ pub struct OpaqueTypeDecl<'tcx> { /// 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, + pub span: Span, /// The type variable that represents the value of the opaque type /// that we require. In other words, after we compile this function, @@ -53,22 +116,21 @@ pub struct OpaqueTypeDecl<'tcx> { /// 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, + pub ty: Ty<'tcx>, } impl<'a, 'tcx> InferCtxt<'a, 'tcx> { - /// Replaces all opaque types in `value` with fresh inference variables + /// Links the opaque type with the given hidden type /// and creates appropriate obligations. For example, given the input: /// - /// impl Iterator + /// opaque = impl Iterator + /// hidden = std::vec::IntoIter /// - /// this method would create two type variables, `?0` and `?1`. It would - /// return the type `?0` but also the obligations: + /// this method would register the opaque type `impl Iterator` to have + /// the hidden type `std::vec::IntoIter` and create the type variable + /// `?1` but also the obligations: /// - /// ?0: Iterator + /// std::vec::IntoIter: Iterator /// ?1: Debug /// /// Moreover, it returns an `OpaqueTypeMap` that would map `?0` to @@ -85,22 +147,73 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// obligations /// - `value` -- the value within which we are instantiating opaque types /// - `value_span` -- the span where the value came from, used in error reporting - pub fn instantiate_opaque_types>( + pub fn instantiate_opaque_types( &self, - body_id: hir::HirId, + ty: Ty<'tcx>, + opaque: Ty<'tcx>, + cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, - value: T, - value_span: Span, - ) -> InferOk<'tcx, T> { - debug!( - "instantiate_opaque_types(value={:?}, body_id={:?}, \ - param_env={:?}, value_span={:?})", - value, body_id, param_env, value_span, - ); - 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, obligations: instantiator.obligations } + ) -> Option>> { + let mut obligations = vec![]; + let value = Instantiator { infcx: self, cause, param_env, obligations: &mut obligations } + .fold_opaque_ty_new(opaque, |_, _| ty)?; + Some(InferOk { value, obligations }) + } + + pub fn handle_opaque_type( + &self, + a: Ty<'tcx>, + b: Ty<'tcx>, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> Result, TypeError<'tcx>> { + if a.references_error() || b.references_error() { + return Ok(vec![]); + } + if self.defining_use_anchor.is_some() { + let process = |a: Ty<'tcx>, b: Ty<'tcx>| { + if !matches!(a.kind(), ty::Opaque(..)) { + return None; + } + self.instantiate_opaque_types(b, a, cause.clone(), param_env) + .map(|res| res.obligations) + }; + if let Some(res) = process(a, b) { + Ok(res) + } else if let Some(res) = process(b, a) { + Ok(res) + } else { + // Rerun equality check, but this time error out due to + // different types. + match self.at(cause, param_env).define_opaque_types(false).eq(a, b) { + Ok(_) => span_bug!( + cause.span, + "opaque types are never equal to anything but themselves: {:#?}", + (a, b) + ), + Err(e) => Err(e), + } + } + } else { + let (opaque_type, hidden_ty) = match (a.kind(), b.kind()) { + (ty::Opaque(..), _) => (a, b), + (_, ty::Opaque(..)) => (b, a), + types => span_bug!( + cause.span, + "opaque type obligations only work for opaque types: {:#?}", + types + ), + }; + let key = opaque_type.expect_opaque_type(); + let origin = self.opaque_ty_origin_unchecked(key.def_id, cause.span); + self.inner.borrow_mut().opaque_types().register( + key, + opaque_type, + OpaqueHiddenType { ty: hidden_ty, span: cause.span }, + origin, + ); + Ok(vec![]) + } } /// Given the map `opaque_types` containing the opaque @@ -268,18 +381,20 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { #[instrument(level = "debug", skip(self))] pub fn constrain_opaque_type( &self, + param_env: ty::ParamEnv<'tcx>, opaque_type_key: OpaqueTypeKey<'tcx>, - opaque_defn: &OpaqueTypeDecl<'tcx>, - ) { + concrete_ty: Ty<'tcx>, + span: Span, + ) -> InferResult<'tcx, ()> { let def_id = opaque_type_key.def_id; let tcx = self.tcx; - let concrete_ty = self.resolve_vars_if_possible(opaque_defn.concrete_ty); + let concrete_ty = self.resolve_vars_if_possible(concrete_ty); debug!(?concrete_ty); - let first_own_region = match opaque_defn.origin { + let first_own_region = match self.opaque_ty_origin_unchecked(def_id, span) { hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => { // We lower // @@ -323,24 +438,44 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { op: |r| { self.member_constraint( opaque_type_key.def_id, - opaque_defn.definition_span, + span, concrete_ty, r, &choice_regions, ) }, }); + Ok(InferOk { value: (), obligations: vec![] }) } - fn opaque_type_origin(&self, def_id: LocalDefId) -> Option { - let tcx = self.tcx; - let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + pub fn opaque_ty_obligation( + &self, + a: Ty<'tcx>, + b: Ty<'tcx>, + a_is_expected: bool, + param_env: ty::ParamEnv<'tcx>, + cause: ObligationCause<'tcx>, + ) -> PredicateObligation<'tcx> { + let (a, b) = if a_is_expected { (a, b) } else { (b, a) }; + PredicateObligation::new( + cause, + param_env, + self.tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::OpaqueType(a, b))), + ) + } + + #[instrument(skip(self), level = "trace")] + pub fn opaque_type_origin(&self, opaque_def_id: DefId, span: Span) -> Option { + let def_id = opaque_def_id.as_local()?; + let opaque_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); let parent_def_id = self.defining_use_anchor?; - let item_kind = &tcx.hir().expect_item(def_id).kind; + let item_kind = &self.tcx.hir().expect_item(def_id).kind; + let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item_kind else { span_bug!( - tcx.def_span(def_id), - "weird opaque type: {:#?}", + span, + "weird opaque type: {:#?}, {:#?}", + opaque_def_id, item_kind ) }; @@ -351,12 +486,26 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id, // Named `type Foo = impl Bar;` hir::OpaqueTyOrigin::TyAlias => { - may_define_opaque_type(tcx, parent_def_id, opaque_hir_id) + may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id) } }; + trace!(?origin); in_definition_scope.then_some(*origin) } + #[instrument(skip(self), level = "trace")] + fn opaque_ty_origin_unchecked(&self, opaque_def_id: DefId, span: Span) -> OpaqueTyOrigin { + let def_id = opaque_def_id.as_local().unwrap(); + let origin = match self.tcx.hir().expect_item(def_id).kind { + hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => origin, + ref itemkind => { + span_bug!(span, "weird opaque type: {:?}, {:#?}", opaque_def_id, itemkind) + } + }; + trace!(?origin); + origin + } + pub fn opaque_types(&self) -> OpaqueTypeMap<'tcx> { self.inner.borrow().opaque_type_storage.opaque_types() } @@ -434,177 +583,166 @@ where } } +pub enum UseKind { + DefiningUse, + OpaqueUse, +} + +impl UseKind { + pub fn is_defining(self) -> bool { + match self { + UseKind::DefiningUse => true, + UseKind::OpaqueUse => false, + } + } +} + struct Instantiator<'a, 'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, - body_id: hir::HirId, + cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, - value_span: Span, - obligations: Vec>, + obligations: &'a mut PredicateObligations<'tcx>, } impl<'a, 'tcx> Instantiator<'a, 'tcx> { - fn instantiate_opaque_types_in_map>(&mut self, value: T) -> T { - let tcx = self.infcx.tcx; - value.fold_with(&mut BottomUpFolder { - tcx, - ty_op: |ty| { - if ty.references_error() { - return tcx.ty_error(); - } else if let ty::Opaque(def_id, substs) = ty.kind() { - // Check that this is `impl Trait` type is - // declared by `parent_def_id` -- i.e., one whose - // value we are inferring. At present, this is - // always true during the first phase of - // type-check, but not always true later on during - // NLL. Once we support named opaque types more fully, - // this same scenario will be able to arise during all phases. - // - // Here is an example using type alias `impl Trait` - // that indicates the distinction we are checking for: - // - // ```rust - // mod a { - // pub type Foo = impl Iterator; - // pub fn make_foo() -> Foo { .. } - // } - // - // mod b { - // fn foo() -> a::Foo { a::make_foo() } - // } - // ``` - // - // Here, the return type of `foo` references an - // `Opaque` indeed, but not one whose value is - // presently being inferred. You can get into a - // similar situation with closure return types - // today: - // - // ```rust - // fn foo() -> impl Iterator { .. } - // fn bar() { - // let x = || foo(); // returns the Opaque assoc with `foo` - // } - // ``` - if let Some(def_id) = def_id.as_local() { - if let Some(origin) = self.infcx.opaque_type_origin(def_id) { - let opaque_type_key = - OpaqueTypeKey { def_id: def_id.to_def_id(), substs }; - return self.fold_opaque_ty(ty, opaque_type_key, origin); - } + #[instrument(level = "trace", skip(self))] + fn instantiate_opaque_types(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + if let Some(ty) = self.fold_opaque_ty_new(ty, |infcx, span| { + infcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span, + }) + }) { + return ty; + } - debug!( - "instantiate_opaque_types_in_map: \ - encountered opaque outside its definition scope \ - def_id={:?}", - def_id, - ); - } - } + ty + } - ty - }, - lt_op: |lt| lt, - ct_op: |ct| ct, - }) + fn fold_opaque_ty_new( + &mut self, + ty: Ty<'tcx>, + mk_ty: impl FnOnce(&InferCtxt<'_, 'tcx>, Span) -> Ty<'tcx>, + ) -> Option> { + // Check that this is `impl Trait` type is + // declared by `parent_def_id` -- i.e., one whose + // value we are inferring. At present, this is + // always true during the first phase of + // type-check, but not always true later on during + // NLL. Once we support named opaque types more fully, + // this same scenario will be able to arise during all phases. + // + // Here is an example using type alias `impl Trait` + // that indicates the distinction we are checking for: + // + // ```rust + // mod a { + // pub type Foo = impl Iterator; + // pub fn make_foo() -> Foo { .. } + // } + // + // mod b { + // fn foo() -> a::Foo { a::make_foo() } + // } + // ``` + // + // Here, the return type of `foo` references an + // `Opaque` indeed, but not one whose value is + // presently being inferred. You can get into a + // similar situation with closure return types + // today: + // + // ```rust + // fn foo() -> impl Iterator { .. } + // fn bar() { + // let x = || foo(); // returns the Opaque assoc with `foo` + // } + // ``` + let opaque_type_key = ty.expect_opaque_type(); + if let Some(origin) = self.infcx.opaque_type_origin(opaque_type_key.def_id, self.cause.span) + { + return Some(self.fold_opaque_ty(ty, opaque_type_key, origin, mk_ty)); + } + + debug!(?ty, "encountered opaque outside its definition scope",); + None } - #[instrument(skip(self), level = "debug")] + #[instrument(skip(self, mk_ty), level = "debug")] fn fold_opaque_ty( &mut self, ty: Ty<'tcx>, opaque_type_key: OpaqueTypeKey<'tcx>, origin: hir::OpaqueTyOrigin, + mk_ty: impl FnOnce(&InferCtxt<'_, 'tcx>, Span) -> Ty<'tcx>, ) -> Ty<'tcx> { let infcx = self.infcx; let tcx = infcx.tcx; let OpaqueTypeKey { def_id, substs } = opaque_type_key; - // 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) = - infcx.inner.borrow().opaque_type_storage.get_decl(&opaque_type_key) - { - debug!("re-using cached concrete type {:?}", opaque_defn.concrete_ty.kind()); - return opaque_defn.concrete_ty; - } - - let ty_var = infcx.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, - span: self.value_span, - }); + let ty_var = mk_ty(infcx, self.cause.span); // Ideally, we'd get the span where *this specific `ty` came // from*, but right now we just use the span from the overall // value being folded. In simple cases like `-> impl Foo`, // these are the same span, but not in cases like `-> (impl // Foo, impl Bar)`. - let definition_span = self.value_span; + let span = self.cause.span; self.infcx.inner.borrow_mut().opaque_types().register( OpaqueTypeKey { def_id, substs }, - OpaqueTypeDecl { opaque_type: ty, definition_span, concrete_ty: ty_var, origin }, + ty, + OpaqueHiddenType { ty: ty_var, span }, + origin, ); debug!("generated new type inference var {:?}", ty_var.kind()); let item_bounds = tcx.explicit_item_bounds(def_id); - self.obligations.reserve(item_bounds.len()); for (predicate, _) in item_bounds { debug!(?predicate); let predicate = predicate.subst(tcx, substs); - debug!(?predicate); let predicate = predicate.fold_with(&mut BottomUpFolder { tcx, ty_op: |ty| match *ty.kind() { + // We can't normalize associated types from `rustc_infer`, + // but we can eagerly register inference variables for them. + ty::Projection(projection_ty) if !projection_ty.has_escaping_bound_vars() => infcx.infer_projection( + self.param_env, + projection_ty, + self.cause.clone(), + 0, + &mut self.obligations, + ), // Replace all other mentions of the same opaque type with the hidden type, // as the bounds must hold on the hidden type after all. ty::Opaque(def_id2, substs2) if def_id == def_id2 && substs == substs2 => { ty_var } - // Instantiate nested instances of `impl Trait`. - ty::Opaque(..) => self.instantiate_opaque_types_in_map(ty), - _ => ty, - }, - lt_op: |lt| lt, - ct_op: |ct| ct, - }); - - // We can't normalize associated types from `rustc_infer`, but we can eagerly register inference variables for them. - let predicate = predicate.fold_with(&mut BottomUpFolder { - tcx, - ty_op: |ty| match ty.kind() { - ty::Projection(projection_ty) if !projection_ty.has_escaping_bound_vars() => { - infcx.infer_projection( - self.param_env, - *projection_ty, - traits::ObligationCause::misc(self.value_span, self.body_id), - 0, - &mut self.obligations, - ) - } + ty::Opaque(..) => self.instantiate_opaque_types(ty), _ => ty, }, lt_op: |lt| lt, ct_op: |ct| ct, }); - debug!(?predicate); if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() { if projection.term.references_error() { + // No point on adding these obligations since there's a type error involved. return tcx.ty_error(); } + trace!("{:#?}", projection.term); } - - let cause = - traits::ObligationCause::new(self.value_span, self.body_id, traits::OpaqueType); - // Require that the predicate holds for the concrete type. debug!(?predicate); - self.obligations.push(traits::Obligation::new(cause, self.param_env, predicate)); + self.obligations.push(traits::Obligation::new( + self.cause.clone(), + self.param_env, + predicate, + )); } - ty_var } } diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs index a660cfaf9462c..dc47272c4fe05 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/table.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -1,11 +1,11 @@ -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::undo_log::UndoLogs; +use rustc_hir::OpaqueTyOrigin; use rustc_middle::ty::{self, OpaqueTypeKey, Ty}; use rustc_span::DUMMY_SP; -use crate::infer::InferCtxtUndoLogs; +use crate::infer::{InferCtxtUndoLogs, UndoLog}; -use super::{OpaqueTypeDecl, OpaqueTypeMap}; +use super::{OpaqueHiddenType, OpaqueTypeDecl, OpaqueTypeMap}; #[derive(Default, Debug)] pub struct OpaqueTypeStorage<'tcx> { @@ -14,21 +14,18 @@ pub struct OpaqueTypeStorage<'tcx> { // 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> OpaqueTypeStorage<'tcx> { #[instrument(level = "debug")] - pub(crate) fn remove(&mut self, key: OpaqueTypeKey<'tcx>) { - match self.opaque_types.remove(&key) { - None => bug!("reverted opaque type inference that was never registered"), - Some(decl) => assert_ne!(self.opaque_types_vars.remove(decl.concrete_ty), None), + pub(crate) fn remove(&mut self, key: OpaqueTypeKey<'tcx>, idx: usize) { + if idx == 0 { + match self.opaque_types.remove(&key) { + None => bug!("reverted opaque type inference that was never registered: {:?}", key), + Some(_) => {} + } + } else { + self.opaque_types.get_mut(&key).unwrap().hidden_types.drain(idx..); } } @@ -36,10 +33,6 @@ impl<'tcx> OpaqueTypeStorage<'tcx> { self.opaque_types.get(key) } - pub fn get_opaque_type_for_infer_var(&self, key: Ty<'tcx>) -> Option> { - self.opaque_types_vars.get(key).copied() - } - pub fn opaque_types(&self) -> OpaqueTypeMap<'tcx> { self.opaque_types.clone() } @@ -76,9 +69,20 @@ pub struct OpaqueTypeTable<'a, 'tcx> { impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> { #[instrument(skip(self), level = "debug")] - pub fn register(&mut self, key: OpaqueTypeKey<'tcx>, decl: OpaqueTypeDecl<'tcx>) { - self.undo_log.push(key); + pub fn register( + &mut self, + key: OpaqueTypeKey<'tcx>, + opaque_type: Ty<'tcx>, + ty: OpaqueHiddenType<'tcx>, + origin: OpaqueTyOrigin, + ) { + if let Some(decl) = self.storage.opaque_types.get_mut(&key) { + decl.hidden_types.push(ty); + self.undo_log.push(UndoLog::OpaqueTypes(key, decl.hidden_types.len())); + return; + } + let decl = OpaqueTypeDecl { opaque_type, hidden_types: vec![ty], origin }; self.storage.opaque_types.insert(key, decl); - self.storage.opaque_types_vars.insert(decl.concrete_ty, decl.opaque_type); + self.undo_log.push(UndoLog::OpaqueTypes(key, 0)); } } diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 03d6c45a65345..b60ffc1878be4 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -28,6 +28,7 @@ pub fn explicit_outlives_bounds<'tcx>( | ty::PredicateKind::TypeOutlives(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => { Some(OutlivesBound::RegionSubRegion(r_b, r_a)) diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index a5276afc5bfa7..d554d7d935c52 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -153,6 +153,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// This function may have to perform normalizations, and hence it /// returns an `InferOk` with subobligations that must be /// processed. + #[instrument(level = "debug", skip(self, region_bound_pairs_map))] pub fn process_registered_region_obligations( &self, region_bound_pairs_map: &FxHashMap>, @@ -164,8 +165,6 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { "cannot process registered region obligations in a snapshot" ); - debug!(?param_env, "process_registered_region_obligations()"); - let my_region_obligations = self.take_registered_region_obligations(); for (body_id, RegionObligation { sup_type, sub_region, origin }) in my_region_obligations { diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index ccac0efd6c9ee..e0a8219beede1 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -2,6 +2,7 @@ use super::combine::{CombineFields, RelationDir}; use super::SubregionOrigin; use crate::infer::combine::ConstEquateRelation; +use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::traits::Obligation; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation}; @@ -74,9 +75,8 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { } } + #[instrument(skip(self), level = "debug")] fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { - debug!("{}.tys({:?}, {:?})", self.tag(), a, b); - if a == b { return Ok(a); } @@ -84,6 +84,7 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { let infcx = self.fields.infcx; let a = infcx.inner.borrow_mut().type_variables().replace_if_possible(a); let b = infcx.inner.borrow_mut().type_variables().replace_if_possible(b); + match (a.kind(), b.kind()) { (&ty::Infer(TyVar(_)), &ty::Infer(TyVar(_))) => { // Shouldn't have any LBR here, so we can safely put @@ -121,6 +122,40 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { Ok(self.tcx().ty_error()) } + (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => { + self.fields.infcx.super_combine_tys(self, a, b)?; + Ok(a) + } + (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..)) + if self.fields.define_opaque_types && did.is_local() => + { + let mut generalize = |ty, ty_is_expected| { + let var = infcx.next_ty_var_id_in_universe( + TypeVariableOrigin { + kind: TypeVariableOriginKind::MiscVariable, + span: self.fields.trace.cause.span, + }, + ty::UniverseIndex::ROOT, + ); + self.fields.instantiate(ty, RelationDir::SubtypeOf, var, ty_is_expected)?; + Ok(infcx.tcx.mk_ty_var(var)) + }; + let (a, b) = if self.a_is_expected { (a, b) } else { (b, a) }; + let (a, b) = match (a.kind(), b.kind()) { + (&ty::Opaque(..), _) => (a, generalize(b, true)?), + (_, &ty::Opaque(..)) => (generalize(a, false)?, b), + _ => unreachable!(), + }; + self.fields.obligations.push(infcx.opaque_ty_obligation( + a, + b, + true, + self.param_env(), + self.fields.trace.cause.clone(), + )); + Ok(a) + } + _ => { self.fields.infcx.super_combine_tys(self, a, b)?; Ok(a) diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs index 3c8a163de5482..8f4abfde3010a 100644 --- a/compiler/rustc_infer/src/infer/undo_log.rs +++ b/compiler/rustc_infer/src/infer/undo_log.rs @@ -18,7 +18,7 @@ pub struct Snapshot<'tcx> { /// Records the "undo" data for a single operation that affects some form of inference variable. pub(crate) enum UndoLog<'tcx> { - OpaqueTypes(OpaqueTypeKey<'tcx>), + OpaqueTypes(OpaqueTypeKey<'tcx>, usize), TypeVariables(type_variable::UndoLog<'tcx>), ConstUnificationTable(sv::UndoLog>>), IntUnificationTable(sv::UndoLog>), @@ -43,7 +43,6 @@ macro_rules! impl_from { // Upcast from a single kind of "undoable action" to the general enum impl_from! { - OpaqueTypes(OpaqueTypeKey<'tcx>), RegionConstraintCollector(region_constraints::UndoLog<'tcx>), TypeVariables(type_variable::UndoLog<'tcx>), @@ -66,7 +65,7 @@ impl_from! { impl<'tcx> Rollback> for InferCtxtInner<'tcx> { fn reverse(&mut self, undo: UndoLog<'tcx>) { match undo { - UndoLog::OpaqueTypes(key) => self.opaque_type_storage.remove(key), + UndoLog::OpaqueTypes(key, idx) => self.opaque_type_storage.remove(key, idx), UndoLog::TypeVariables(undo) => self.type_variable_storage.reverse(undo), UndoLog::ConstUnificationTable(undo) => self.const_unification_storage.reverse(undo), UndoLog::IntUnificationTable(undo) => self.int_unification_storage.reverse(undo), diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 674c75fdee561..6600d5e4d0279 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -167,6 +167,9 @@ impl<'tcx> Elaborator<'tcx> { // Currently, we do not elaborate WF predicates, // although we easily could. } + ty::PredicateKind::OpaqueType(..) => { + todo!("{:#?}", obligation) + } ty::PredicateKind::ObjectSafe(..) => { // Currently, we do not elaborate object-safe // predicates. diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 734b32bb92f1e..442e756715b77 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1654,6 +1654,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { Coerce(..) | ConstEvaluatable(..) | ConstEquate(..) | + OpaqueType(..) | TypeWellFormedFromEnv(..) => continue, }; if predicate.is_global() { diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 28217aeab13ee..cc83010580f98 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -23,7 +23,7 @@ use crate::infer::MemberConstraint; use crate::ty::subst::GenericArg; -use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt}; +use crate::ty::{self, BoundVar, List, OpaqueTypeKey, Region, Ty, TyCtxt}; use rustc_index::vec::IndexVec; use rustc_macros::HashStable; use smallvec::SmallVec; @@ -178,6 +178,9 @@ pub struct QueryResponse<'tcx, R> { pub var_values: CanonicalVarValues<'tcx>, pub region_constraints: QueryRegionConstraints<'tcx>, pub certainty: Certainty, + /// List of opaque types for which we figured out a hidden type + /// during the evaluation of the query. + pub opaque_types: Vec<(OpaqueTypeKey<'tcx>, Vec>)>, pub value: R, } diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs index e0e3febe6b310..2642bddb9a4d3 100644 --- a/compiler/rustc_middle/src/ty/_match.rs +++ b/compiler/rustc_middle/src/ty/_match.rs @@ -53,17 +53,17 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> { self.relate(a, b) } + #[instrument(skip(self), level = "debug")] fn regions( &mut self, a: ty::Region<'tcx>, b: ty::Region<'tcx>, ) -> RelateResult<'tcx, ty::Region<'tcx>> { - debug!("{}.regions({:?}, {:?})", self.tag(), a, b); Ok(a) } + #[instrument(skip(self), level = "debug")] fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { - debug!("{}.tys({:?}, {:?})", self.tag(), a, b); if a == b { return Ok(a); } diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index f06a1b09cd82a..7394bc5b2d8dd 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -265,6 +265,10 @@ impl FlagComputation { ty::PredicateKind::TypeWellFormedFromEnv(ty) => { self.add_ty(ty); } + ty::PredicateKind::OpaqueType(opaque, ty) => { + self.add_ty(opaque); + self.add_ty(ty); + } } } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 3133cdfdd7a72..2fd0ca423cc94 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -1207,15 +1207,11 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { type BreakTy = FoundFlags; #[inline] - #[instrument(level = "trace")] - fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow { - debug!( - "HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}", - t, - t.flags(), - self.flags - ); - if t.flags().intersects(self.flags) { + #[instrument(skip(self), level = "trace")] + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + let flags = t.flags(); + trace!(t.flags=?t.flags()); + if flags.intersects(self.flags) { ControlFlow::Break(FoundFlags) } else { ControlFlow::CONTINUE @@ -1235,7 +1231,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { } #[inline] - #[instrument(level = "trace")] + #[instrument(skip(self), level = "trace")] fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow { let flags = FlagComputation::for_const(c); trace!(r.flags=?flags); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 78878487a9b48..d052b87577d2c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -628,6 +628,11 @@ pub enum PredicateKind<'tcx> { /// /// Only used for Chalk. TypeWellFormedFromEnv(Ty<'tcx>), + + /// Represents a hidden type assignment for an opaque type. + /// Such obligations get processed by checking whether the item currently being + /// type-checked may acually define it. + OpaqueType(Ty<'tcx>, Ty<'tcx>), } /// The crate outlives map is computed during typeck and contains the @@ -987,6 +992,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::TypeOutlives(..) | PredicateKind::ConstEvaluatable(..) | PredicateKind::ConstEquate(..) + | PredicateKind::OpaqueType(..) | PredicateKind::TypeWellFormedFromEnv(..) => None, } } @@ -1005,6 +1011,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::ClosureKind(..) | PredicateKind::ConstEvaluatable(..) | PredicateKind::ConstEquate(..) + | PredicateKind::OpaqueType(..) | PredicateKind::TypeWellFormedFromEnv(..) => None, } } @@ -1045,7 +1052,18 @@ impl<'tcx> InstantiatedPredicates<'tcx> { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable, TypeFoldable)] +#[derive( + Copy, + Clone, + Debug, + PartialEq, + Eq, + HashStable, + TyEncodable, + TyDecodable, + TypeFoldable, + Lift +)] pub struct OpaqueTypeKey<'tcx> { pub def_id: DefId, pub substs: SubstsRef<'tcx>, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index ddcc8680d8352..62a0143817a9c 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2607,6 +2607,9 @@ define_print_and_forward_display! { ty::PredicateKind::TypeWellFormedFromEnv(ty) => { p!("the type `", print(ty), "` is found in the environment") } + ty::PredicateKind::OpaqueType(a, b) => { + p!("opaque type assigment with `", print(a), "` == `", print(b) ,"`") + } } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 1c5bc7860db2d..ef54832791d41 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -191,6 +191,9 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(ty) => { write!(f, "TypeWellFormedFromEnv({:?})", ty) } + ty::PredicateKind::OpaqueType(a, b) => { + write!(f, "OpaqueType({:?}, {:?})", a.kind(), b.kind()) + } } } } @@ -463,6 +466,9 @@ impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> { ty::PredicateKind::TypeWellFormedFromEnv(ty) => { tcx.lift(ty).map(ty::PredicateKind::TypeWellFormedFromEnv) } + ty::PredicateKind::OpaqueType(opaque, ty) => { + Some(ty::PredicateKind::OpaqueType(tcx.lift(opaque)?, tcx.lift(ty)?)) + } } } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index a53d5f6626bb2..6b187f7da4c6d 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1816,6 +1816,13 @@ impl<'tcx> TyS<'tcx> { } } + pub fn expect_opaque_type(&self) -> ty::OpaqueTypeKey<'tcx> { + match *self.kind() { + Opaque(def_id, substs) => ty::OpaqueTypeKey { def_id, substs }, + _ => bug!("`expect_opaque_type` called on non-opaque type: {}", self), + } + } + pub fn simd_size_and_type(&self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) { match self.kind() { Adt(def, substs) => { diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index df71379c1d886..8cb19baa29230 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -1,8 +1,8 @@ use crate::build::matches::ArmHasGuard; use crate::build::ForGuard::OutsideGuard; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; -use rustc_middle::mir::*; use rustc_middle::thir::*; +use rustc_middle::{mir::*, ty}; use rustc_session::lint::builtin::UNSAFE_OP_IN_UNSAFE_FN; use rustc_session::lint::Level; use rustc_span::Span; @@ -192,7 +192,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // This return type is usually `()`, unless the block is diverging, in which case the // return type is `!`. For the unit type, we need to actually return the unit, but in // the case of `!`, no return value is required, as the block will never return. - if destination_ty.is_unit() { + // Opaque types of empty bodies also need this unit assignment, in order to infer that their + // type is actually unit. Otherwise there will be no defining use found in the MIR. + if destination_ty.is_unit() || matches!(destination_ty.kind(), ty::Opaque(..)) { // We only want to assign an implicit `()` as the return value of the block if the // block does not diverge. (Otherwise, we may try to assign a unit to a `!`-type.) this.cfg.push_assign_unit(block, source_info, destination, this.tcx); diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index 283eda7c85e64..545a7bc7d7d8a 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -186,7 +186,6 @@ impl EncoderState { } } - #[instrument(level = "debug", skip(self, record_graph))] fn encode_node( &mut self, node: &NodeInfo, @@ -213,7 +212,6 @@ impl EncoderState { stat.edge_counter += edge_count as u64; } - debug!(?index, ?node); let encoder = &mut self.encoder; if self.result.is_ok() { self.result = node.encode(encoder); diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index ea0ac6318bc9a..6b0910b475ff2 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -359,6 +359,7 @@ crate fn required_region_bounds<'tcx>( | ty::PredicateKind::RegionOutlives(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => { // Search for a bound of the form `erased_self_ty diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index f2ed5ae26a3c2..da04fb2cd2104 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -853,6 +853,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { | ty::PredicateKind::Subtype(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::Coerce(..) + | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => {} }; } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 6cb19416cd769..8624137d77687 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -775,6 +775,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { span, "TypeWellFormedFromEnv predicate should only exist in the environment" ), + + ty::PredicateKind::OpaqueType(..) => { + todo!("{:#?}", obligation); + } } } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index e7897887df706..68dd1cd261683 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -397,6 +397,9 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } + ty::PredicateKind::OpaqueType(..) => { + todo!("{:#?}", obligation); + } }, Some(pred) => match pred { ty::PredicateKind::Trait(data) => { @@ -642,6 +645,20 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } + ty::PredicateKind::OpaqueType(a, b) => { + match self.selcx.infcx().handle_opaque_type( + a, + b, + &obligation.cause, + obligation.param_env, + ) { + Ok(value) => ProcessResult::Changed(mk_pending(value)), + Err(err) => ProcessResult::Error(FulfillmentErrorCode::CodeSubtypeError( + ExpectedFound::new(true, a, b), + err, + )), + } + } }, } } diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 7818053218dec..cd6f381333ad0 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -313,6 +313,7 @@ fn predicate_references_self<'tcx>( | ty::PredicateKind::Coerce(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, } } @@ -347,6 +348,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool { | ty::PredicateKind::TypeOutlives(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => false, } }) diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs index 0a85676f4315e..3aa5ee366f78f 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs @@ -3,7 +3,7 @@ use crate::infer::{InferCtxt, InferOk}; use crate::traits::engine::TraitEngineExt as _; use crate::traits::query::type_op::TypeOpOutput; use crate::traits::query::Fallible; -use crate::traits::{ObligationCause, TraitEngine}; +use crate::traits::TraitEngine; use rustc_infer::traits::TraitEngineExt as _; use rustc_span::source_map::DUMMY_SP; @@ -60,7 +60,6 @@ fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>( op: impl FnOnce() -> Fallible>, ) -> Fallible> { let mut fulfill_cx = >::new(infcx.tcx); - let dummy_body_id = ObligationCause::dummy().body_id; // During NLL, we expect that nobody will register region // obligations **except** as part of a custom type op (and, at the @@ -75,7 +74,6 @@ fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>( ); let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?; - debug_assert!(obligations.iter().all(|o| o.cause.body_id == dummy_body_id)); fulfill_cx.register_predicate_obligations(infcx, obligations); let errors = fulfill_cx.select_all_or_error(infcx); if !errors.is_empty() { diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index db86041f6180b..0c5d764e79d0c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -254,6 +254,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }; if obligation.predicate.skip_binder().self_ty().is_ty_var() { + debug!(ty = ?obligation.predicate.skip_binder().self_ty(), "ambiguous inference var or opaque type"); // Self is a type variable (e.g., `_: AsRef`). // // This is somewhat problematic, as the current scheme can't really diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 47427395b93b3..3b99183d8eb1f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -37,6 +37,7 @@ use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::thir::abstract_const::NotConstEvaluatable; use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences}; +use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef}; @@ -697,6 +698,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for chalk") } + ty::PredicateKind::OpaqueType(a, b) => { + match self.infcx().handle_opaque_type( + a, + b, + &obligation.cause, + obligation.param_env, + ) { + Ok(obligations) => { + self.evaluate_predicates_recursively(previous_stack, obligations) + } + Err(_) => Ok(EvaluatedToErr), + } + } } }); @@ -1337,6 +1351,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + #[instrument(skip(self, param_env, cache_fresh_trait_pred, dep_node), level = "debug")] fn insert_candidate_cache( &mut self, mut param_env: ty::ParamEnv<'tcx>, @@ -1377,6 +1392,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// a projection, look at the bounds of `T::Bar`, see if we can find a /// `Baz` bound. We return indexes into the list returned by /// `tcx.item_bounds` for any applicable bounds. + #[instrument(level = "debug", skip(self))] fn match_projection_obligation_against_definition_bounds( &mut self, obligation: &TraitObligation<'tcx>, @@ -1384,10 +1400,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let poly_trait_predicate = self.infcx().resolve_vars_if_possible(obligation.predicate); let placeholder_trait_predicate = self.infcx().replace_bound_vars_with_placeholders(poly_trait_predicate); - debug!( - ?placeholder_trait_predicate, - "match_projection_obligation_against_definition_bounds" - ); + debug!(?placeholder_trait_predicate); let tcx = self.infcx.tcx; let (def_id, substs) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() { @@ -1438,7 +1451,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }) .collect(); - debug!(?matching_bounds, "match_projection_obligation_against_definition_bounds"); + debug!(?matching_bounds); matching_bounds } @@ -1468,6 +1481,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }); self.infcx .at(&obligation.cause, obligation.param_env) + .define_opaque_types(false) .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound) .map(|InferOk { obligations: _, value: () }| { // This method is called within a probe, so we can't have @@ -1523,6 +1537,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx .at(&obligation.cause, obligation.param_env) + .define_opaque_types(false) .sup(obligation.predicate, infer_projection) .map_or(false, |InferOk { obligations, value: () }| { self.evaluate_predicates_recursively( @@ -2081,11 +2096,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match self.match_impl(impl_def_id, obligation) { Ok(substs) => substs, Err(()) => { - bug!( - "Impl {:?} was matchable against {:?} but now is not", - impl_def_id, - obligation + self.infcx.tcx.sess.delay_span_bug( + obligation.cause.span, + &format!( + "Impl {:?} was matchable against {:?} but now is not", + impl_def_id, obligation + ), ); + let value = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id); + let err = self.tcx().ty_error(); + let value = value.fold_with(&mut BottomUpFolder { + tcx: self.tcx(), + ty_op: |_| err, + lt_op: |l| l, + ct_op: |c| c, + }); + Normalized { value, obligations: vec![] } } } } @@ -2222,6 +2248,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result>, ()> { self.infcx .at(&obligation.cause, obligation.param_env) + // We don't want opaque types to just randomly match everything, + // they should be opaque, even in their defining scope. + .define_opaque_types(false) .sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref) .map(|InferOk { obligations, .. }| obligations) .map_err(|_| ()) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 493cb199f1144..68707fee44f99 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -146,6 +146,10 @@ pub fn predicate_obligations<'a, 'tcx>( wf.compute(c1.into()); wf.compute(c2.into()); } + ty::PredicateKind::OpaqueType(opaque, ty) => { + wf.compute(opaque.into()); + wf.compute(ty.into()); + } ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 67d0ba39667d3..71ea77dc37910 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -110,6 +110,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment bug!("unexpected predicate {}", predicate), }; @@ -196,6 +197,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predi | ty::PredicateKind::Subtype(..) | ty::PredicateKind::Coerce(..) | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::ConstEquate(..) => { chalk_ir::GoalData::All(chalk_ir::Goals::empty(interner)) } @@ -610,6 +612,7 @@ impl<'tcx> LowerInto<'tcx, Option { bug!("unexpected predicate {}", &self) } @@ -739,6 +742,7 @@ impl<'tcx> LowerInto<'tcx, Option { bug!("unexpected predicate {}", &self) } diff --git a/compiler/rustc_traits/src/chalk/mod.rs b/compiler/rustc_traits/src/chalk/mod.rs index 09bfdabf47373..287538e0764d3 100644 --- a/compiler/rustc_traits/src/chalk/mod.rs +++ b/compiler/rustc_traits/src/chalk/mod.rs @@ -142,6 +142,7 @@ crate fn evaluate_goal<'tcx>( var_values: CanonicalVarValues { var_values }, region_constraints: QueryRegionConstraints::default(), certainty: Certainty::Proven, + opaque_types: vec![], value: (), }, }; @@ -170,6 +171,7 @@ crate fn evaluate_goal<'tcx>( .make_identity(tcx), region_constraints: QueryRegionConstraints::default(), certainty: Certainty::Ambiguous, + opaque_types: vec![], value: (), }, }; diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index 90c698db8fb54..1535a46a01b47 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -105,6 +105,7 @@ fn compute_implied_outlives_bounds<'tcx>( | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => vec![], ty::PredicateKind::WellFormed(arg) => { wf_args.push(arg); diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index 46c2f7e4cf2ed..c64e97074a6e0 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -69,6 +69,7 @@ fn not_outlives_predicate<'tcx>(p: &ty::Predicate<'tcx>) -> bool { | ty::PredicateKind::Coerce(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => true, } } diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index ec6fb622d32aa..94476ee2c4101 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -61,6 +61,12 @@ bitflags! { | TypeFlags::HAS_CT_INFER.bits | TypeFlags::HAS_TY_PLACEHOLDER.bits | TypeFlags::HAS_CT_PLACEHOLDER.bits + // Opaque types may get resolved in the current scope and must + // thus not be transported to other queries if it can be avoided. + // FIXME: differentiate between crate-local opaque types + // and opaque types from other crates, as only opaque types + // from the local crate can possibly be a local name + | TypeFlags::HAS_TY_OPAQUE.bits // We consider 'freshened' types and constants // to depend on a particular fn. // The freshening process throws away information, diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index 405e4e8594a3a..bc5662b596093 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -504,20 +504,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // provide a structured suggestion in that case. pub(crate) fn opt_suggest_box_span( &self, - span: Span, + _span: Span, outer_ty: &'tcx TyS<'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(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 { diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs index 0fea0afb572c9..19c3f00ed9357 100644 --- a/compiler/rustc_typeck/src/check/callee.rs +++ b/compiler/rustc_typeck/src/check/callee.rs @@ -545,7 +545,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Expectation<'tcx>, fn_sig: ty::FnSig<'tcx>, ) -> Ty<'tcx> { - // `fn_sig` is the *signature* of the cosure being called. We + // `fn_sig` is the *signature* of the closure being called. We // don't know the full details yet (`Fn` vs `FnMut` etc), but we // do know the types expected for each argument and the return // type. diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 7983b6ea0b2c0..3405619f403b2 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -17,7 +17,7 @@ use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::layout::MAX_SIMD_LANES; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::util::{Discr, IntTypeExt}; -use rustc_middle::ty::{self, OpaqueTypeKey, ParamEnv, RegionKind, Ty, TyCtxt}; +use rustc_middle::ty::{self, ParamEnv, RegionKind, Ty, TyCtxt}; use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS}; use rustc_span::symbol::sym; use rustc_span::{self, MultiSpan, Span}; @@ -81,8 +81,6 @@ pub(super) fn check_fn<'a, 'tcx>( can_be_generator: Option, return_type_pre_known: bool, ) -> (FnCtxt<'a, 'tcx>, Option>) { - let mut fn_sig = fn_sig; - // Create the function context. This is either derived from scratch or, // in the case of closures, based on the outer context. let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id); @@ -95,21 +93,13 @@ pub(super) fn check_fn<'a, 'tcx>( let declared_ret_ty = fn_sig.output(); - 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_coercion = Some(RefCell::new(CoerceMany::new(declared_ret_ty))); fcx.ret_type_span = Some(decl.output.span()); if let ty::Opaque(..) = declared_ret_ty.kind() { + // FIXME(oli-obk): remove this and have diagnostics check the signature's return type directly + // as we don't reveal here anymore. fcx.ret_coercion_impl_trait = Some(declared_ret_ty); } - fn_sig = tcx.mk_fn_sig( - fn_sig.inputs().iter().cloned(), - revealed_ret_ty, - fn_sig.c_variadic, - fn_sig.unsafety, - fn_sig.abi, - ); let span = body.value.span; @@ -251,7 +241,7 @@ pub(super) fn check_fn<'a, 'tcx>( fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::DynReturnFn, span }); debug!("actual_return_ty replaced with {:?}", actual_return_ty); } - fcx.demand_suptype(span, revealed_ret_ty, actual_return_ty); + fcx.demand_suptype(span, declared_ret_ty, actual_return_ty); // Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !` if let Some(panic_impl_did) = tcx.lang_items().panic_impl() { @@ -629,6 +619,8 @@ fn check_opaque_meets_bounds<'tcx>( span: Span, origin: &hir::OpaqueTyOrigin, ) { + let hidden_type = tcx.type_of(def_id).subst(tcx, substs); + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let defining_use_anchor = match *origin { hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did, @@ -643,23 +635,12 @@ fn check_opaque_meets_bounds<'tcx>( let misc_cause = traits::ObligationCause::misc(span, hir_id); - let _ = inh.register_infer_ok_obligations( - infcx.instantiate_opaque_types(hir_id, param_env, opaque_ty, span), - ); - - for (OpaqueTypeKey { def_id, substs }, opaque_defn) in infcx.opaque_types() { - let hidden_type = tcx.type_of(def_id).subst(tcx, substs); - trace!(?hidden_type); - match infcx.at(&misc_cause, param_env).eq(opaque_defn.concrete_ty, hidden_type) { - Ok(infer_ok) => inh.register_infer_ok_obligations(infer_ok), - Err(ty_err) => tcx.sess.delay_span_bug( - span, - &format!( - "could not check bounds on revealed type `{}`:\n{}", - hidden_type, ty_err, - ), - ), - } + match infcx.at(&misc_cause, param_env).eq(opaque_ty, hidden_type) { + Ok(infer_ok) => inh.register_infer_ok_obligations(infer_ok), + Err(ty_err) => tcx.sess.delay_span_bug( + span, + &format!("could not unify `{}` with revealed type:\n{}", hidden_type, ty_err,), + ), } // Check that all obligations are satisfied by the implementation's @@ -671,7 +652,7 @@ fn check_opaque_meets_bounds<'tcx>( match origin { // Checked when type checking the function containing them. - hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => return, + hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {} // Can have different predicates to their defining use hir::OpaqueTyOrigin::TyAlias => { // Finally, resolve all regions. This catches wily misuses of @@ -680,6 +661,9 @@ fn check_opaque_meets_bounds<'tcx>( fcx.regionck_item(hir_id, span, FxHashSet::default()); } } + + // Clean up after ourselves + let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); }); } diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index e88099afa0353..d4336563b9603 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -3,16 +3,20 @@ use super::{check_fn, Expectation, FnCtxt, GeneratorTypes}; use crate::astconv::AstConv; +use crate::rustc_middle::ty::subst::Subst; +use hir::OpaqueTyOrigin; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::infer::{InferOk, InferResult}; +use rustc_infer::traits::ObligationCause; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::{self, Ty}; use rustc_span::source_map::Span; +use rustc_span::DUMMY_SP; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits::error_reporting::ArgKind; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; @@ -172,6 +176,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty: Ty<'tcx>, ) -> (Option>, Option) { match *expected_ty.kind() { + ty::Opaque(def_id, substs) => { + let bounds = self.tcx.explicit_item_bounds(def_id); + let sig = bounds.iter().find_map(|(pred, span)| match pred.kind().skip_binder() { + ty::PredicateKind::Projection(proj_predicate) => self + .deduce_sig_from_projection( + Some(*span), + pred.kind().rebind(proj_predicate.subst(self.tcx, substs)), + ), + _ => None, + }); + + let kind = bounds + .iter() + .filter_map(|(pred, _)| match pred.kind().skip_binder() { + ty::PredicateKind::Trait(tp) => { + self.tcx.fn_trait_kind_from_lang_item(tp.def_id()) + } + _ => None, + }) + .fold(None, |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur)))); + trace!(?sig, ?kind); + (sig, kind) + } ty::Dynamic(ref object_type, ..) => { let sig = object_type.projection_bounds().find_map(|pb| { let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self); @@ -197,10 +224,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> (Option>, Option) { let expected_sig = self.obligations_for_self_ty(expected_vid).find_map(|(_, obligation)| { - debug!( - "deduce_expectations_from_obligations: obligation.predicate={:?}", - obligation.predicate - ); + debug!(?obligation.predicate); let bound_predicate = obligation.predicate.kind(); if let ty::PredicateKind::Projection(proj_predicate) = @@ -401,9 +425,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // in this binder we are creating. assert!(!expected_sig.sig.skip_binder().has_vars_bound_above(ty::INNERMOST)); let bound_sig = expected_sig.sig.map_bound(|sig| { + let output = self.hide_parent_opaque_types( + sig.output(), + expected_sig.cause_span.unwrap_or(DUMMY_SP), + body.id().hir_id, + ); self.tcx.mk_fn_sig( sig.inputs().iter().cloned(), - sig.output(), + output, sig.c_variadic, hir::Unsafety::Normal, Abi::RustCall, @@ -590,6 +619,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => astconv.ty_infer(None, decl.output.span()), }, }; + let supplied_return = + self.hide_parent_opaque_types(supplied_return, decl.output.span(), body.id().hir_id); let result = ty::Binder::bind_with_vars( self.tcx.mk_fn_sig( @@ -610,27 +641,57 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { result } + fn hide_parent_opaque_types(&self, ty: Ty<'tcx>, span: Span, body_id: hir::HirId) -> Ty<'tcx> { + ty.fold_with(&mut ty::fold::BottomUpFolder { + tcx: self.infcx.tcx, + lt_op: |lt| lt, + ct_op: |ct| ct, + ty_op: |ty| match *ty.kind() { + // Closures can't create hidden types for opaque types of their parent, as they + // do not have all the outlives information available. Also `type_of` looks for + // hidden types in the owner (so the closure's parent), so it would not find these + // definitions. + ty::Opaque(def_id, _substs) + if matches!( + self.infcx.opaque_type_origin(def_id, DUMMY_SP), + Some(OpaqueTyOrigin::FnReturn(..)) + ) => + { + let ty_var = self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span, + }); + let cause = ObligationCause::misc(span, body_id); + self.register_predicates(vec![self.infcx.opaque_ty_obligation( + ty, + ty_var, + true, + self.param_env, + cause, + )]); + ty_var + } + _ => ty, + }, + }) + } + /// Invoked when we are translating the generator that results /// from desugaring an `async fn`. Returns the "sugared" return /// type of the `async fn` -- that is, the return type that the /// user specified. The "desugared" return type is an `impl /// Future`, so we do this by searching through the /// obligations to extract the `T`. + #[instrument(skip(self), level = "debug")] fn deduce_future_output_from_obligations(&self, expr_def_id: DefId) -> Option> { - debug!("deduce_future_output_from_obligations(expr_def_id={:?})", expr_def_id); - let ret_coercion = self.ret_coercion.as_ref().unwrap_or_else(|| { span_bug!(self.tcx.def_span(expr_def_id), "async fn generator outside of a fn") }); - // In practice, the return type of the surrounding function is - // always a (not yet resolved) inference variable, because it - // is the hidden type for an `impl Trait` that we are going to - // be inferring. let ret_ty = ret_coercion.borrow().expected_ty(); let ret_ty = self.inh.infcx.shallow_resolve(ret_ty); - let ret_vid = match *ret_ty.kind() { - ty::Infer(ty::TyVar(ret_vid)) => ret_vid, + let (def_id, substs) = match *ret_ty.kind() { + ty::Opaque(def_id, substs) => (def_id, substs), ty::Error(_) => return None, _ => span_bug!( self.tcx.def_span(expr_def_id), @@ -638,17 +699,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), }; + let item_bounds = self.tcx.explicit_item_bounds(def_id); + // Search for a pending obligation like // // `::Output = T` // // where R is the return type we are expecting. This type `T` // will be our output. - let output_ty = self.obligations_for_self_ty(ret_vid).find_map(|(_, obligation)| { - let bound_predicate = obligation.predicate.kind(); + let output_ty = item_bounds.iter().find_map(|&(predicate, span)| { + let bound_predicate = predicate.subst(self.tcx, substs).kind(); if let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder() { self.deduce_future_output_from_projection( - obligation.cause.span, + span, bound_predicate.rebind(proj_predicate), ) } else { diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 3668ecd234c64..8204a25e9112b 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -1275,7 +1275,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { /// Returns the current "merged type", representing our best-guess /// at the LUB of the expressions we've seen so far (if any). This - /// isn't *final* until you call `self.final()`, which will return + /// isn't *final* until you call `self.complete()`, which will return /// the merged type. pub fn merged_ty(&self) -> Ty<'tcx> { self.final_ty.unwrap_or(self.expected_ty) diff --git a/compiler/rustc_typeck/src/check/expectation.rs b/compiler/rustc_typeck/src/check/expectation.rs index e9e810344776b..9e1a70b7dfb92 100644 --- a/compiler/rustc_typeck/src/check/expectation.rs +++ b/compiler/rustc_typeck/src/check/expectation.rs @@ -1,5 +1,6 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_middle::ty::{self, Ty}; +use rustc_span::DUMMY_SP; use rustc_span::{self, Span}; use super::Expectation::*; @@ -43,7 +44,7 @@ impl<'a, 'tcx> Expectation<'tcx> { // when checking the 'then' block which are incompatible with the // 'else' branch. pub(super) fn adjust_for_branches(&self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> { - match *self { + match self.strip_opaque(fcx) { ExpectHasType(ety) => { let ety = fcx.shallow_resolve(ety); if !ety.is_ty_var() { ExpectHasType(ety) } else { NoExpectation } @@ -104,14 +105,35 @@ impl<'a, 'tcx> Expectation<'tcx> { /// for the program to type-check). `only_has_type` will return /// such a constraint, if it exists. pub(super) fn only_has_type(self, fcx: &FnCtxt<'a, 'tcx>) -> Option> { - match self { - ExpectHasType(ty) => Some(fcx.resolve_vars_if_possible(ty)), + match self.strip_opaque(fcx) { + ExpectHasType(ty) => Some(ty), NoExpectation | ExpectCastableToType(_) | ExpectRvalueLikeUnsized(_) | IsLast(_) => { None } } } + /// We must not treat opaque types as expected types in their defining scope, as that + /// will break `fn foo() -> impl Trait { if cond { a } else { b } }` if `a` and `b` are + /// only "equal" if they coerce to a common target, like two different function items + /// coercing to a function pointer if they have the same signature. + fn strip_opaque(self, fcx: &FnCtxt<'a, 'tcx>) -> Self { + match self { + ExpectHasType(ty) => { + let ty = fcx.resolve_vars_if_possible(ty); + match *ty.kind() { + ty::Opaque(def_id, _) + if fcx.infcx.opaque_type_origin(def_id, DUMMY_SP).is_some() => + { + NoExpectation + } + _ => self, + } + } + _ => self, + } + } + /// Like `only_has_type`, but instead of returning `None` if no /// hard constraint exists, creates a fresh type variable. pub(super) fn coercion_target_type(self, fcx: &FnCtxt<'a, 'tcx>, span: Span) -> Ty<'tcx> { diff --git a/compiler/rustc_typeck/src/check/fallback.rs b/compiler/rustc_typeck/src/check/fallback.rs index d062a0cc55f4e..bbe34977c911a 100644 --- a/compiler/rustc_typeck/src/check/fallback.rs +++ b/compiler/rustc_typeck/src/check/fallback.rs @@ -24,7 +24,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { self.fulfillment_cx.borrow_mut().pending_obligations() ); - // Check if we have any unsolved varibales. If not, no need for fallback. + // Check if we have any unsolved variables. If not, no need for fallback. let unsolved_variables = self.unsolved_variables(); if unsolved_variables.is_empty() { return false; @@ -66,16 +66,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> { // refer to opaque types. self.select_obligations_where_possible(fallback_has_occurred, |_| {}); - // We now run fallback again, but this time we allow it to replace - // unconstrained opaque type variables, in addition to performing - // other kinds of fallback. - for ty in &self.unsolved_variables() { - fallback_has_occurred |= self.fallback_opaque_type_vars(ty); - } - - // See if we can make any more progress. - self.select_obligations_where_possible(fallback_has_occurred, |_| {}); - fallback_has_occurred } @@ -136,59 +126,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> { true } - /// Second round of fallback: Unconstrained type variables created - /// from the instantiation of an opaque type fall back to the - /// opaque type itself. This is a somewhat incomplete attempt to - /// manage "identity passthrough" for `impl Trait` types. - /// - /// For example, in this code: - /// - ///``` - /// type MyType = impl Copy; - /// fn defining_use() -> MyType { true } - /// fn other_use() -> MyType { defining_use() } - /// ``` - /// - /// `defining_use` will constrain the instantiated inference - /// variable to `bool`, while `other_use` will constrain - /// the instantiated inference variable to `MyType`. - /// - /// When we process opaque types during writeback, we - /// will handle cases like `other_use`, and not count - /// them as defining usages - /// - /// However, we also need to handle cases like this: - /// - /// ```rust - /// pub type Foo = impl Copy; - /// fn produce() -> Option { - /// None - /// } - /// ``` - /// - /// In the above snippet, the inference variable created by - /// instantiating `Option` will be completely unconstrained. - /// We treat this as a non-defining use by making the inference - /// variable fall back to the opaque type itself. - fn fallback_opaque_type_vars(&self, ty: Ty<'tcx>) -> bool { - let span = self - .infcx - .type_var_origin(ty) - .map(|origin| origin.span) - .unwrap_or(rustc_span::DUMMY_SP); - let oty = self.inner.borrow().opaque_type_storage.get_opaque_type_for_infer_var(ty); - if let Some(opaque_ty) = oty { - debug!( - "fallback_opaque_type_vars(ty={:?}): falling back to opaque type {:?}", - ty, opaque_ty - ); - self.demand_eqtype(span, ty, opaque_ty); - true - } else { - return false; - } - } - /// The "diverging fallback" system is rather complicated. This is /// a result of our need to balance 'do the right thing' with /// backwards compatibility. @@ -281,7 +218,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { .diverging_type_vars .borrow() .iter() - .map(|&ty| self.infcx.shallow_resolve(ty)) + .map(|(&ty, _)| self.infcx.shallow_resolve(ty)) .filter_map(|ty| ty.ty_vid()) .map(|vid| self.infcx.root_var(vid)) .collect(); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 0f9803b969fb7..705b3207999a7 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -274,7 +274,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for a in &adj { if let Adjust::NeverToAny = a.kind { if a.target.is_ty_var() { - self.diverging_type_vars.borrow_mut().insert(a.target); + self.diverging_type_vars.borrow_mut().insert(a.target, expr.span); debug!("apply_adjustments: adding `{:?}` as diverging type var", a.target); } } @@ -367,23 +367,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (result, spans) } - /// 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, - value: T, - value_span: Span, - ) -> T { - 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 /// that occurs as a result of WF checking. The `hir_id` is the `HirId` of the hir item /// whose type is being wf-checked - this is used to construct a more precise span if @@ -720,6 +703,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // inference variable. ty::PredicateKind::ClosureKind(..) => None, ty::PredicateKind::TypeWellFormedFromEnv(..) => None, + ty::PredicateKind::OpaqueType(..) => None, } }) .filter(move |(tr, _)| self.self_type_matches_expected_vid(*tr, ty_var_root)) diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs index beb6b371b2bb8..c9b843aedb2d4 100644 --- a/compiler/rustc_typeck/src/check/inherited.rs +++ b/compiler/rustc_typeck/src/check/inherited.rs @@ -1,7 +1,7 @@ use super::callee::DeferredCallResolution; use super::MaybeInProgressTables; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_hir::def_id::{DefIdMap, LocalDefId}; use rustc_hir::HirIdMap; @@ -58,7 +58,7 @@ pub struct Inherited<'a, 'tcx> { /// Whenever we introduce an adjustment from `!` into a type variable, /// we record that type variable here. This is later used to inform /// fallback. See the `fallback` module for details. - pub(super) diverging_type_vars: RefCell>>, + pub(super) diverging_type_vars: RefCell, Span>>, } impl<'a, 'tcx> Deref for Inherited<'a, 'tcx> { @@ -95,6 +95,13 @@ impl<'tcx> InheritedBuilder<'tcx> { let def_id = self.def_id; self.infcx.enter(|infcx| f(Inherited::new(infcx, def_id))) } + + /// WF-checking doesn't need to recompute opaque types and can instead use + /// the type_of query to get them from typeck. + pub fn reveal_defining_opaque_types(mut self) -> Self { + self.infcx = self.infcx.reveal_defining_opaque_types(); + self + } } impl<'a, 'tcx> Inherited<'a, 'tcx> { @@ -119,8 +126,8 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self))] pub(super) fn register_predicate(&self, obligation: traits::PredicateObligation<'tcx>) { - debug!("register_predicate({:?})", obligation); if obligation.has_escaping_bound_vars() { span_bug!(obligation.cause.span, "escaping bound vars in predicate {:?}", obligation); } diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 3815fd1992bf3..b8a45133fd7ea 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -858,6 +858,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { | ty::PredicateKind::TypeOutlives(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, } }); @@ -1477,6 +1478,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { TraitCandidate(trait_ref) => self.probe(|_| { let _ = self .at(&ObligationCause::dummy(), self.param_env) + .define_opaque_types(false) .sup(candidate.xform_self_ty, self_ty); match self.select_trait_candidate(trait_ref) { Ok(Some(traits::ImplSource::UserDefined(ref impl_data))) => { @@ -1506,6 +1508,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // First check that the self type can be related. let sub_obligations = match self .at(&ObligationCause::dummy(), self.param_env) + .define_opaque_types(false) .sup(probe.xform_self_ty, self_ty) { Ok(InferOk { obligations, value: () }) => obligations, @@ -1653,6 +1656,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ); if self .at(&ObligationCause::dummy(), self.param_env) + .define_opaque_types(false) .sup(return_ty, xform_ret_ty) .is_err() { diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 6e0b902a00bda..5094806e75f4a 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -99,6 +99,8 @@ pub use diverges::Diverges; pub use expectation::Expectation; pub use fn_ctxt::*; pub use inherited::{Inherited, InheritedBuilder}; +use rustc_infer::traits::ObligationCause; +use traits::ObligationCauseCode::MiscObligation; use crate::astconv::AstConv; use crate::check::gather_locals::GatherLocalsVisitor; @@ -341,6 +343,7 @@ fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::T typeck_with_fallback(tcx, def_id, fallback) } +#[instrument(skip(tcx, fallback))] fn typeck_with_fallback<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, @@ -471,6 +474,19 @@ fn typeck_with_fallback<'tcx>( fcx.require_type_is_sized(ty, span, code); } + let opaque_types = fcx.infcx.inner.borrow_mut().opaque_type_storage.opaque_types(); + for (_, decl) in opaque_types { + let cause = ObligationCause::new(body.value.span, id, MiscObligation); + if let Err((err, expected, actual)) = + decl.hidden_type(&fcx.infcx, &cause, fcx.param_env) + { + let cause = ObligationCause::new(actual.span, id, MiscObligation); + fcx.report_mismatched_types(&cause, expected.ty, actual.ty, err) + .span_label(expected.span, "type expected due to this") + .emit(); + } + } + fcx.select_all_obligations_or_error(); if fn_sig.is_some() { diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 71f45320e4952..c0fa673774ffd 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -895,7 +895,7 @@ fn for_item<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>) -> CheckWfFcxBuilder< fn for_id(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> CheckWfFcxBuilder<'_> { CheckWfFcxBuilder { - inherited: Inherited::build(tcx, def_id), + inherited: Inherited::build(tcx, def_id).reveal_defining_opaque_types(), id: hir::HirId::make_owner(def_id), span, param_env: tcx.param_env(def_id), diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index e4c9cdbeef3f4..f97fedd9a6dab 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -18,7 +18,6 @@ use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::Span; -use rustc_trait_selection::opaque_types::InferCtxtExt; use std::mem; @@ -65,7 +64,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { wbcx.visit_closures(); wbcx.visit_liberated_fn_sigs(); wbcx.visit_fru_field_types(); - wbcx.visit_opaque_types(body.value.span); + wbcx.visit_opaque_types(); wbcx.visit_coercion_casts(); wbcx.visit_user_provided_tys(); wbcx.visit_user_provided_sigs(); @@ -496,65 +495,12 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fcx_typeck_results.generator_interior_types.clone(); } - #[instrument(skip(self, span), level = "debug")] - fn visit_opaque_types(&mut self, span: Span) { + #[instrument(skip(self), level = "debug")] + fn visit_opaque_types(&mut self) { let opaque_types = self.fcx.infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); - 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); - - debug_assert!(!instantiated_ty.has_escaping_bound_vars()); - - let opaque_type_key = self.fcx.fully_resolve(opaque_type_key).unwrap(); - - // Prevent: - // * `fn foo() -> Foo` - // * `fn foo() -> Foo` - // from being defining. - - // Also replace all generic params with the ones from the opaque type - // definition so that - // ```rust - // type Foo = impl Baz + 'static; - // fn foo() -> Foo { .. } - // ``` - // figures out the concrete type with `U`, but the stored type is with `T`. - - // FIXME: why are we calling this here? This seems too early, and duplicated. - let definition_ty = self.fcx.infer_opaque_definition_from_instantiation( - opaque_type_key, - instantiated_ty, - span, - ); - - let mut skip_add = false; - - if let ty::Opaque(definition_ty_def_id, _substs) = *definition_ty.kind() { - if opaque_defn.origin == hir::OpaqueTyOrigin::TyAlias { - if opaque_type_key.def_id == definition_ty_def_id { - debug!( - "skipping adding concrete definition for opaque type {:?} {:?}", - opaque_defn, opaque_type_key.def_id - ); - skip_add = true; - } - } - } - - if opaque_type_key.substs.needs_infer() { - span_bug!(span, "{:#?} has inference variables", opaque_type_key.substs) - } - - // We only want to add an entry into `concrete_opaque_types` - // if we actually found a defining usage of this opaque type. - // Otherwise, we do nothing - we'll either find a defining usage - // in some other location, or we'll end up emitting an error due - // to the lack of defining usage - if !skip_add { - self.typeck_results.concrete_opaque_types.insert(opaque_type_key.def_id); - } + for (opaque_type_key, _) in opaque_types { + self.typeck_results.concrete_opaque_types.insert(opaque_type_key.def_id); } } diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 5cb0d309ff4ee..ce2f486bb7043 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -389,13 +389,6 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { .get_value_matching(|(key, _)| key.def_id == def_id.to_def_id()) .copied() .unwrap_or_else(|| { - tcx.sess.delay_span_bug( - DUMMY_SP, - &format!( - "owner {:?} has no opaque type for {:?} in its typeck results", - owner, def_id, - ), - ); if let Some(ErrorReported) = tcx.typeck(owner).tainted_by_errors { @@ -405,12 +398,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { tcx.ty_error() } else { // We failed to resolve the opaque type or it - // resolves to itself. Return the non-revealed - // type, which should result in E0720. - tcx.mk_opaque( - def_id.to_def_id(), - InternalSubsts::identity_for_item(tcx, def_id.to_def_id()), - ) + // resolves to itself. We interpret this as the + // no values of the hidden type ever being constructed, + // so we can just make the hidden type be `!`. + // For backwards compatibility reasons, we fall back to + // `()` until we the diverging default is changed. + tcx.mk_diverging_default() } }); debug!("concrete_ty = {:?}", concrete_ty); @@ -658,7 +651,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { intravisit::walk_expr(self, ex); } fn visit_item(&mut self, it: &'tcx Item<'tcx>) { - debug!("find_existential_constraints: visiting {:?}", it); + trace!(?it.def_id); // The opaque type itself or its children are not within its reveal scope. if it.def_id.to_def_id() != self.def_id { self.check(it.def_id); @@ -666,7 +659,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { } } fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) { - debug!("find_existential_constraints: visiting {:?}", it); + trace!(?it.def_id); // The opaque type itself or its children are not within its reveal scope. if it.def_id.to_def_id() != self.def_id { self.check(it.def_id); @@ -674,7 +667,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { } } fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) { - debug!("find_existential_constraints: visiting {:?}", it); + trace!(?it.def_id); self.check(it.def_id); intravisit::walk_trait_item(self, it); } @@ -684,12 +677,12 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { let scope = tcx.hir().get_defining_scope(hir_id); let mut locator = ConstraintLocator { def_id: def_id.to_def_id(), tcx, found: None }; - debug!("find_opaque_ty_constraints: scope={:?}", scope); + debug!(?scope); if scope == hir::CRATE_HIR_ID { tcx.hir().walk_toplevel_module(&mut locator); } else { - debug!("find_opaque_ty_constraints: scope={:?}", tcx.hir().get(scope)); + trace!("scope={:#?}", tcx.hir().get(scope)); match tcx.hir().get(scope) { // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods // This allows our visitor to process the defining item itself, causing diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs index d87e670a8fb5a..4227ed6ab3ad5 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -427,6 +427,7 @@ fn trait_predicate_kind<'tcx>( | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, } } diff --git a/compiler/rustc_typeck/src/outlives/explicit.rs b/compiler/rustc_typeck/src/outlives/explicit.rs index bbf31de527eb3..7839ce5e4ff48 100644 --- a/compiler/rustc_typeck/src/outlives/explicit.rs +++ b/compiler/rustc_typeck/src/outlives/explicit.rs @@ -59,6 +59,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { | ty::PredicateKind::Coerce(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => (), } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7d209accec9b5..3fdc904bd327c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -297,6 +297,7 @@ impl<'a> Clean> for ty::Predicate<'a> { | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"), } } diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs index 4124eada188e8..31564a0cbd5c6 100644 --- a/src/test/incremental/hashes/function_interfaces.rs +++ b/src/test/incremental/hashes/function_interfaces.rs @@ -305,7 +305,7 @@ pub fn return_impl_trait() -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig, optimized_mir")] #[rustc_clean(cfg = "cfail3")] #[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, typeck, fn_sig, optimized_mir")] #[rustc_clean(cfg = "cfail6")] 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 4c36289f47b85..ac3df7fca5ab2 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,10 @@ impl Bar for AssocNoCopy { impl Thing for AssocNoCopy { type Out = Box>; + //~^ ERROR could not find defining uses fn func() -> Self::Out { - //~^ ERROR the trait bound `String: Copy` is not satisfied Box::new(AssocNoCopy) + //~^ ERROR the trait bound `String: Copy` is not satisfied } } 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 a32ab453152a0..3cbc3358d07fb 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,9 +1,17 @@ error[E0277]: the trait bound `String: Copy` is not satisfied - --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:32:18 + --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:34:9 | -LL | fn func() -> Self::Out { - | ^^^^^^^^^ the trait `Copy` is not implemented for `String` +LL | Box::new(AssocNoCopy) + | ^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + | + = note: required for the cast to the object type `dyn Bar` + +error: could not find defining uses + --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:30:28 + | +LL | type Out = Box>; + | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/impl-trait-return-missing-constraint.rs b/src/test/ui/associated-types/impl-trait-return-missing-constraint.rs index 5f994f26534bd..30e4c1a3c537b 100644 --- a/src/test/ui/associated-types/impl-trait-return-missing-constraint.rs +++ b/src/test/ui/associated-types/impl-trait-return-missing-constraint.rs @@ -23,8 +23,8 @@ fn bar() -> impl Bar { } fn baz() -> impl Bar { -//~^ ERROR type mismatch resolving `::Item == i32` bar() + //~^ ERROR type mismatch resolving `::Item == i32` } fn main() { diff --git a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr index 283ecea735d41..9523a54d954df 100644 --- a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr +++ b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr @@ -1,14 +1,16 @@ error[E0271]: type mismatch resolving `::Item == i32` - --> $DIR/impl-trait-return-missing-constraint.rs:25:13 + --> $DIR/impl-trait-return-missing-constraint.rs:26:5 | LL | fn bar() -> impl Bar { - | -------- the found opaque type + | -------- the expected opaque type ... -LL | fn baz() -> impl Bar { - | ^^^^^^^^^^^^^^^^^^^^ expected `i32`, found associated type +LL | bar() + | ^^^^^ expected associated type, found `i32` | - = note: expected type `i32` - found associated type `::Item` + = note: expected associated type `::Item` + found type `i32` + = help: consider constraining the associated type `::Item` to `i32` or calling a method that returns `::Item` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html help: consider constraining the associated type `::Item` to `i32` | LL | fn bar() -> impl Bar { diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr index 44d60c1d80d88..f21c811512416 100644 --- a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr +++ b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr @@ -8,10 +8,10 @@ LL | Box::new(async { x } ) | may outlive borrowed value `x` | note: async block is returned here - --> $DIR/async-borrowck-escaping-block-error.rs:4:20 + --> $DIR/async-borrowck-escaping-block-error.rs:6:5 | -LL | fn test_boxed() -> Box> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Box::new(async { x } ) + | ^^^^^^^^^^^^^^^^^^^^^^ help: to force the async block to take ownership of `x` (and any other referenced variables), use the `move` keyword | LL | Box::new(async move { x } ) diff --git a/src/test/ui/async-await/async-error-span.rs b/src/test/ui/async-await/async-error-span.rs index 86d459bf084b1..338483ff6acdc 100644 --- a/src/test/ui/async-await/async-error-span.rs +++ b/src/test/ui/async-await/async-error-span.rs @@ -5,8 +5,7 @@ use std::future::Future; fn get_future() -> impl Future { -//~^ ERROR `()` is not a future - panic!() + panic!() //~^ ERROR `()` is not a future } async fn foo() { diff --git a/src/test/ui/async-await/async-error-span.stderr b/src/test/ui/async-await/async-error-span.stderr index 7d4447b6d5578..18e8dd940fa06 100644 --- a/src/test/ui/async-await/async-error-span.stderr +++ b/src/test/ui/async-await/async-error-span.stderr @@ -8,13 +8,13 @@ LL | fn get_future() -> impl Future { = note: () must be a future or must implement `IntoFuture` to be awaited error[E0698]: type inside `async fn` body must be known in this context - --> $DIR/async-error-span.rs:13:9 + --> $DIR/async-error-span.rs:12:9 | LL | let a; | ^ cannot infer type | note: the type is part of the `async fn` body because of this `await` - --> $DIR/async-error-span.rs:14:17 + --> $DIR/async-error-span.rs:13:17 | LL | get_future().await; | ^^^^^^ diff --git a/src/test/ui/async-await/issue-64130-4-async-move.rs b/src/test/ui/async-await/issue-64130-4-async-move.rs index 2538f34351e5a..7cb02e5cf383d 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.rs +++ b/src/test/ui/async-await/issue-64130-4-async-move.rs @@ -13,9 +13,9 @@ impl Client { async fn get() { } pub fn foo() -> impl Future + Send { - //~^ ERROR future cannot be sent between threads safely let client = Client(Box::new(true)); async move { + //~^ ERROR future cannot be sent between threads safely match client.status() { 200 => { let _x = get().await; diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr index d631e6dc7f7e9..2d4327f4ea8ab 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.stderr +++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr @@ -1,8 +1,14 @@ error: future cannot be sent between threads safely - --> $DIR/issue-64130-4-async-move.rs:15:17 + --> $DIR/issue-64130-4-async-move.rs:17:5 | -LL | pub fn foo() -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` +LL | / async move { +LL | | +LL | | match client.status() { +LL | | 200 => { +... | +LL | | } +LL | | } + | |_____^ future created by async block is not `Send` | = help: the trait `Sync` is not implemented for `(dyn Any + Send + 'static)` note: future is not `Send` as this value is used across an await diff --git a/src/test/ui/async-await/issue-70818.rs b/src/test/ui/async-await/issue-70818.rs index 0609e4fc08170..631389e10f316 100644 --- a/src/test/ui/async-await/issue-70818.rs +++ b/src/test/ui/async-await/issue-70818.rs @@ -2,8 +2,8 @@ use std::future::Future; fn foo(ty: T, ty1: U) -> impl Future + Send { -//~^ Error future cannot be sent between threads safely async { (ty, ty1) } + //~^ Error future cannot be sent between threads safely } fn main() {} diff --git a/src/test/ui/async-await/issue-70818.stderr b/src/test/ui/async-await/issue-70818.stderr index 20109d4d1166a..3fc08c18bc0eb 100644 --- a/src/test/ui/async-await/issue-70818.stderr +++ b/src/test/ui/async-await/issue-70818.stderr @@ -1,11 +1,11 @@ error: future cannot be sent between threads safely - --> $DIR/issue-70818.rs:4:38 + --> $DIR/issue-70818.rs:5:5 | -LL | fn foo(ty: T, ty1: U) -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` +LL | async { (ty, ty1) } + | ^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` | note: captured value is not `Send` - --> $DIR/issue-70818.rs:6:18 + --> $DIR/issue-70818.rs:5:18 | LL | async { (ty, ty1) } | ^^^ has type `U` which is not `Send` diff --git a/src/test/ui/async-await/issue-70935-complex-spans.rs b/src/test/ui/async-await/issue-70935-complex-spans.rs index 2965a7e0654a4..494561229511e 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.rs +++ b/src/test/ui/async-await/issue-70935-complex-spans.rs @@ -8,8 +8,8 @@ async fn baz(_c: impl FnMut() -> T) where T: Future { } fn foo(tx: std::sync::mpsc::Sender) -> impl Future + Send { - //~^ ERROR: future cannot be sent between threads safely async move { + //~^ ERROR: future cannot be sent between threads safely baz(|| async{ foo(tx.clone()); }).await; diff --git a/src/test/ui/async-await/issue-70935-complex-spans.stderr b/src/test/ui/async-await/issue-70935-complex-spans.stderr index db3099381196b..c7b6893afd6f1 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.stderr @@ -1,8 +1,13 @@ error: future cannot be sent between threads safely - --> $DIR/issue-70935-complex-spans.rs:10:45 + --> $DIR/issue-70935-complex-spans.rs:11:5 | -LL | fn foo(tx: std::sync::mpsc::Sender) -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` +LL | / async move { +LL | | +LL | | baz(|| async{ +LL | | foo(tx.clone()); +LL | | }).await; +LL | | } + | |_____^ future created by async block is not `Send` | = help: the trait `Sync` is not implemented for `Sender` note: future is not `Send` as this value is used across an await diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr index 2722c72c20a33..ffb113c1d3367 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr @@ -17,14 +17,13 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea --> $DIR/ret-impl-trait-one.rs:16:65 | LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { - | -- ^^^^^^^^^^^^^^ - | | - | hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here + | ^^^^^^^^^^^^^^ | -help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound +note: hidden type `(&'a u8, &' u8)` captures lifetime smaller than the function body + --> $DIR/ret-impl-trait-one.rs:16:65 | -LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b { - | ++++ +LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { + | ^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr index 149692a2c6998..32b4d18c162d4 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr @@ -1,24 +1,26 @@ error[E0623]: lifetime mismatch - --> $DIR/ret-impl-trait-one.rs:10:65 + --> $DIR/ret-impl-trait-one.rs:10:85 | -LL | async fn async_ret_impl_trait3<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b { - | ------ ^^^^^^^^^^^^^^^^^^^ - | | | - | | ...but data from `a` is returned here - | this parameter and the return type are declared with different lifetimes... +LL | async fn async_ret_impl_trait3<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b { + | ______________________________________________________------_____-------------------_^ + | | | + | | this parameter and the return type are declared with different lifetimes... +LL | | +LL | | (a, b) +LL | | } + | |_^ ...but data from `a` is returned here error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds --> $DIR/ret-impl-trait-one.rs:16:65 | LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { - | -- ^^^^^^^^^^^^^^ - | | - | hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here + | ^^^^^^^^^^^^^^ | -help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound +note: hidden type `(&'a u8, &' u8)` captures lifetime smaller than the function body + --> $DIR/ret-impl-trait-one.rs:16:65 | -LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b { - | ++++ +LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { + | ^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/async-await/no-const-async.rs b/src/test/ui/async-await/no-const-async.rs index b3c59734e036f..cfb0ef1b33a2b 100644 --- a/src/test/ui/async-await/no-const-async.rs +++ b/src/test/ui/async-await/no-const-async.rs @@ -3,3 +3,4 @@ pub const async fn x() {} //~^ ERROR functions cannot be both `const` and `async` +//~| ERROR cycle detected diff --git a/src/test/ui/async-await/no-const-async.stderr b/src/test/ui/async-await/no-const-async.stderr index 90ec646c8c09c..fd76c282f9629 100644 --- a/src/test/ui/async-await/no-const-async.stderr +++ b/src/test/ui/async-await/no-const-async.stderr @@ -7,5 +7,36 @@ LL | pub const async fn x() {} | | `async` because of this | `const` because of this -error: aborting due to previous error +error[E0391]: cycle detected when computing type of `x::{opaque#0}` + --> $DIR/no-const-async.rs:4:24 + | +LL | pub const async fn x() {} + | ^ + | +note: ...which requires borrow-checking `x`... + --> $DIR/no-const-async.rs:4:1 + | +LL | pub const async fn x() {} + | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing `x`... + --> $DIR/no-const-async.rs:4:1 + | +LL | pub const async fn x() {} + | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const checking `x`... + --> $DIR/no-const-async.rs:4:1 + | +LL | pub const async fn x() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires computing whether `impl core::future::future::Future` is freeze... + = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future: core::marker::Freeze`... + = note: ...which again requires computing type of `x::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/no-const-async.rs:4:1 + | +LL | pub const async fn x() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/async-await/recursive-async-impl-trait-type.rs b/src/test/ui/async-await/recursive-async-impl-trait-type.rs index aa7733194587d..edc4cb8ac5df3 100644 --- a/src/test/ui/async-await/recursive-async-impl-trait-type.rs +++ b/src/test/ui/async-await/recursive-async-impl-trait-type.rs @@ -2,7 +2,8 @@ // Test that impl trait does not allow creating recursive types that are // otherwise forbidden when using `async` and `await`. -async fn recursive_async_function() -> () { //~ ERROR +async fn recursive_async_function() -> () { + //~^ ERROR recursion in an `async fn` requires boxing recursive_async_function().await; } diff --git a/src/test/ui/async-await/suggest-missing-await.rs b/src/test/ui/async-await/suggest-missing-await.rs index c7c5b51e7334b..046f1dfea3238 100644 --- a/src/test/ui/async-await/suggest-missing-await.rs +++ b/src/test/ui/async-await/suggest-missing-await.rs @@ -21,7 +21,6 @@ async fn dummy() {} async fn suggest_await_in_async_fn_return() { dummy() //~^ ERROR mismatched types [E0308] - //~| HELP consider using a semicolon here //~| HELP consider `await`ing on the `Future` //~| SUGGESTION .await } diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr index 3cca9616a358a..a60571dc11df6 100644 --- a/src/test/ui/async-await/suggest-missing-await.stderr +++ b/src/test/ui/async-await/suggest-missing-await.stderr @@ -33,13 +33,9 @@ help: consider `await`ing on the `Future` | LL | dummy().await | ++++++ -help: consider using a semicolon here - | -LL | dummy(); - | + error[E0308]: `if` and `else` have incompatible types - --> $DIR/suggest-missing-await.rs:35:9 + --> $DIR/suggest-missing-await.rs:34:9 | LL | let _x = if true { | ______________- @@ -53,15 +49,20 @@ LL | | LL | | }; | |_____- `if` and `else` have incompatible types | - = note: expected type `impl Future` - found unit type `()` +note: while checking the return type of the `async fn` + --> $DIR/suggest-missing-await.rs:18:18 + | +LL | async fn dummy() {} + | ^ checked the `Output` of this `async fn`, expected opaque type + = note: expected opaque type `impl Future` + found unit type `()` help: consider `await`ing on the `Future` | LL | dummy().await | ++++++ error[E0308]: `match` arms have incompatible types - --> $DIR/suggest-missing-await.rs:45:14 + --> $DIR/suggest-missing-await.rs:44:14 | LL | let _x = match 0usize { | ______________- @@ -89,7 +90,7 @@ LL ~ 1 => dummy().await, | error[E0308]: mismatched types - --> $DIR/suggest-missing-await.rs:53:9 + --> $DIR/suggest-missing-await.rs:52:9 | LL | () => {} | ^^ expected opaque type, found `()` @@ -107,13 +108,13 @@ LL | let _x = match dummy().await { | ++++++ error[E0308]: mismatched types - --> $DIR/suggest-missing-await.rs:67:9 + --> $DIR/suggest-missing-await.rs:66:9 | LL | Ok(_) => {} | ^^^^^ expected opaque type, found enum `Result` | note: while checking the return type of the `async fn` - --> $DIR/suggest-missing-await.rs:57:28 + --> $DIR/suggest-missing-await.rs:56:28 | LL | async fn dummy_result() -> Result<(), ()> { | ^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, expected opaque type @@ -125,13 +126,13 @@ LL | match dummy_result().await { | ++++++ error[E0308]: mismatched types - --> $DIR/suggest-missing-await.rs:69:9 + --> $DIR/suggest-missing-await.rs:68:9 | LL | Err(_) => {} | ^^^^^^ expected opaque type, found enum `Result` | note: while checking the return type of the `async fn` - --> $DIR/suggest-missing-await.rs:57:28 + --> $DIR/suggest-missing-await.rs:56:28 | LL | async fn dummy_result() -> Result<(), ()> { | ^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, expected opaque type diff --git a/src/test/ui/cast/casts-differing-anon.rs b/src/test/ui/cast/casts-differing-anon.rs index d4a0f9613055e..ccf41adce6bd8 100644 --- a/src/test/ui/cast/casts-differing-anon.rs +++ b/src/test/ui/cast/casts-differing-anon.rs @@ -18,5 +18,5 @@ fn main() { // this is an `*mut fmt::Debug` in practice let mut b_raw = Box::into_raw(b); // ... and they should not be mixable - b_raw = f_raw as *mut _; //~ ERROR is invalid + b_raw = f_raw as *mut _; //~ ERROR mismatched types } diff --git a/src/test/ui/cast/casts-differing-anon.stderr b/src/test/ui/cast/casts-differing-anon.stderr index f9abfb5225f91..2d08903c5ef69 100644 --- a/src/test/ui/cast/casts-differing-anon.stderr +++ b/src/test/ui/cast/casts-differing-anon.stderr @@ -1,11 +1,19 @@ -error[E0606]: casting `*mut impl Debug + ?Sized` as `*mut impl Debug + ?Sized` is invalid +error[E0308]: mismatched types --> $DIR/casts-differing-anon.rs:21:13 | +LL | fn foo() -> Box { + | ---------------------- the found opaque type +... +LL | fn bar() -> Box { + | ---------------------- the expected opaque type +... LL | b_raw = f_raw as *mut _; - | ^^^^^^^^^^^^^^^ + | ^^^^^ expected opaque type, found a different opaque type | - = note: vtable kinds may not match + = note: expected opaque type `impl Debug + ?Sized` (opaque type at <$DIR/casts-differing-anon.rs:7:17>) + found opaque type `impl Debug + ?Sized` (opaque type at <$DIR/casts-differing-anon.rs:3:17>) + = note: distinct uses of `impl Trait` result in different opaque types error: aborting due to previous error -For more information about this error, try `rustc --explain E0606`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr index bb00465758a45..46379a3815a4d 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr @@ -8,10 +8,10 @@ LL | println!("{:?}", p); | - `p` is borrowed here | note: closure is returned here - --> $DIR/borrowck-4.rs:8:14 + --> $DIR/borrowck-4.rs:15:5 | -LL | fn foo () -> impl FnMut()->() { - | ^^^^^^^^^^^^^^^^ +LL | c + | ^ help: to force the closure to take ownership of `p` (and any other referenced variables), use the `move` keyword | LL | let mut c = move || { diff --git a/src/test/ui/conservative_impl_trait.stderr b/src/test/ui/conservative_impl_trait.stderr index 63a4df242f85f..9dc486980aaca 100644 --- a/src/test/ui/conservative_impl_trait.stderr +++ b/src/test/ui/conservative_impl_trait.stderr @@ -1,8 +1,11 @@ error[E0277]: `()` is not an iterator - --> $DIR/conservative_impl_trait.rs:3:33 + --> $DIR/conservative_impl_trait.rs:3:60 | -LL | fn will_ice(something: &u32) -> impl Iterator { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator +LL | fn will_ice(something: &u32) -> impl Iterator { + | ____________________________________________________________^ +LL | | +LL | | } + | |_^ `()` is not an iterator | = help: the trait `Iterator` is not implemented for `()` diff --git a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs index 308c121a94111..b3bd88ad7d5d8 100644 --- a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs +++ b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs @@ -4,8 +4,8 @@ trait Trait {} impl Trait for Uwu {} fn rawr() -> impl Trait { - //~^ error: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied Uwu::<10, 12> + //~^ error: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied } trait Traitor { } @@ -15,13 +15,13 @@ impl Traitor<1, 2> for u64 {} fn uwu() -> impl Traitor { - //~^ error: the trait bound `u32: Traitor` is not satisfied 1_u32 + //~^ error: the trait bound `u32: Traitor` is not satisfied } fn owo() -> impl Traitor { - //~^ error: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied 1_u64 + //~^ error: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied } fn main() { diff --git a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr index 8c8bfdc0e4847..ec23952114cdf 100644 --- a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr +++ b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr @@ -1,26 +1,26 @@ error[E0277]: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied - --> $DIR/rp_impl_trait_fail.rs:6:14 + --> $DIR/rp_impl_trait_fail.rs:7:5 | -LL | fn rawr() -> impl Trait { - | ^^^^^^^^^^ the trait `Trait` is not implemented for `Uwu<10_u32, 12_u32>` +LL | Uwu::<10, 12> + | ^^^^^^^^^^^^^ the trait `Trait` is not implemented for `Uwu<10_u32, 12_u32>` | = help: the following implementations were found: as Trait> error[E0277]: the trait bound `u32: Traitor` is not satisfied - --> $DIR/rp_impl_trait_fail.rs:17:26 + --> $DIR/rp_impl_trait_fail.rs:18:5 | -LL | fn uwu() -> impl Traitor { - | ^^^^^^^^^^^^^^^ the trait `Traitor` is not implemented for `u32` +LL | 1_u32 + | ^^^^^ the trait `Traitor` is not implemented for `u32` | = help: the following implementations were found: > error[E0277]: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied - --> $DIR/rp_impl_trait_fail.rs:22:13 + --> $DIR/rp_impl_trait_fail.rs:23:5 | -LL | fn owo() -> impl Traitor { - | ^^^^^^^^^^^^ the trait `Traitor<1_u8, 1_u8>` is not implemented for `u64` +LL | 1_u64 + | ^^^^^ the trait `Traitor<1_u8, 1_u8>` is not implemented for `u64` | = help: the following implementations were found: > diff --git a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs index e0bb7dbfae9f1..eab5a6190ef51 100644 --- a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs +++ b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs @@ -4,11 +4,9 @@ //~^^^ ERROR `main` function not found in crate pub mod foo { type MainFn = impl Fn(); - //~^ ERROR could not find defining uses fn bar() {} pub const BAR: MainFn = bar; - //~^ ERROR mismatched types [E0308] } use foo::BAR as main; diff --git a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr index c731c32832222..83a189e01e013 100644 --- a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr +++ b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr @@ -12,25 +12,6 @@ LL | | use foo::BAR as main; | | | non-function item at `crate::main` is found -error[E0308]: mismatched types - --> $DIR/imported_main_const_fn_item_type_forbidden.rs:10:29 - | -LL | type MainFn = impl Fn(); - | --------- the expected opaque type -... -LL | pub const BAR: MainFn = bar; - | ^^^ expected opaque type, found fn item - | - = note: expected opaque type `impl Fn()` - found fn item `fn() {bar}` - -error: could not find defining uses - --> $DIR/imported_main_const_fn_item_type_forbidden.rs:6:19 - | -LL | type MainFn = impl Fn(); - | ^^^^^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0308, E0601. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs index ea82837d4bf55..6dfd7f6840f1b 100644 --- a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs +++ b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs @@ -1,13 +1,13 @@ // ignore-compare-mode-chalk +// check-pass #![feature(type_alias_impl_trait)] use std::fmt::Debug; type Foo = impl Debug; -//~^ ERROR could not find defining uses struct Bar(Foo); fn define() -> Bar { - Bar(42) //~ ERROR mismatched types + Bar(42) } type Foo2 = impl Debug; @@ -17,21 +17,18 @@ fn define2() { } type Foo3 = impl Debug; -//~^ ERROR could not find defining uses fn define3(x: Foo3) { - let y: i32 = x; //~ ERROR mismatched types + let y: i32 = x; } fn define3_1() { - define3(42) //~ ERROR mismatched types + define3(42) } type Foo4 = impl Debug; -//~^ ERROR could not find defining uses fn define4() { let y: Foo4 = 42; - //~^ ERROR mismatched types [E0308] } fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr deleted file mode 100644 index da3ddb1c50979..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr +++ /dev/null @@ -1,73 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/feature-gate-type_alias_impl_trait.rs:10:9 - | -LL | type Foo = impl Debug; - | ---------- the expected opaque type -... -LL | Bar(42) - | ^^ expected opaque type, found integer - | - = note: expected opaque type `impl Debug` - found type `{integer}` - -error[E0308]: mismatched types - --> $DIR/feature-gate-type_alias_impl_trait.rs:23:18 - | -LL | type Foo3 = impl Debug; - | ---------- the found opaque type -... -LL | let y: i32 = x; - | --- ^ expected `i32`, found opaque type - | | - | expected due to this - | - = note: expected type `i32` - found opaque type `impl Debug` - -error[E0308]: mismatched types - --> $DIR/feature-gate-type_alias_impl_trait.rs:26:13 - | -LL | type Foo3 = impl Debug; - | ---------- the expected opaque type -... -LL | define3(42) - | ^^ expected opaque type, found integer - | - = note: expected opaque type `impl Debug` - found type `{integer}` - -error[E0308]: mismatched types - --> $DIR/feature-gate-type_alias_impl_trait.rs:33:19 - | -LL | type Foo4 = impl Debug; - | ---------- the expected opaque type -... -LL | let y: Foo4 = 42; - | ---- ^^ expected opaque type, found integer - | | - | expected due to this - | - = note: expected opaque type `impl Debug` - found type `{integer}` - -error: could not find defining uses - --> $DIR/feature-gate-type_alias_impl_trait.rs:5:12 - | -LL | type Foo = impl Debug; - | ^^^^^^^^^^ - -error: could not find defining uses - --> $DIR/feature-gate-type_alias_impl_trait.rs:19:13 - | -LL | type Foo3 = impl Debug; - | ^^^^^^^^^^ - -error: could not find defining uses - --> $DIR/feature-gate-type_alias_impl_trait.rs:29:13 - | -LL | type Foo4 = impl Debug; - | ^^^^^^^^^^ - -error: aborting due to 7 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/generator/issue-88653.rs b/src/test/ui/generator/issue-88653.rs index ce9159b53e0f0..c4905995a860a 100644 --- a/src/test/ui/generator/issue-88653.rs +++ b/src/test/ui/generator/issue-88653.rs @@ -6,10 +6,10 @@ use std::ops::Generator; fn foo(bar: bool) -> impl Generator<(bool,)> { -//~^ ERROR: type mismatch in generator arguments [E0631] -//~| NOTE: expected signature of `fn((bool,)) -> _` |bar| { //~^ NOTE: found signature of `fn(bool) -> _` + //~| ERROR: type mismatch in generator arguments [E0631] + //~| NOTE: expected signature of `fn((bool,)) -> _` if bar { yield bar; } diff --git a/src/test/ui/generator/issue-88653.stderr b/src/test/ui/generator/issue-88653.stderr index 5bd8ad129fef9..a44e273f854ce 100644 --- a/src/test/ui/generator/issue-88653.stderr +++ b/src/test/ui/generator/issue-88653.stderr @@ -1,11 +1,18 @@ error[E0631]: type mismatch in generator arguments - --> $DIR/issue-88653.rs:8:22 + --> $DIR/issue-88653.rs:9:5 | -LL | fn foo(bar: bool) -> impl Generator<(bool,)> { - | ^^^^^^^^^^^^^^^^^^^^^^^ expected signature of `fn((bool,)) -> _` -... -LL | |bar| { - | ----- found signature of `fn(bool) -> _` +LL | |bar| { + | ^---- + | | + | _____found signature of `fn(bool) -> _` + | | +LL | | +LL | | +LL | | +... | +LL | | } +LL | | } + | |_____^ expected signature of `fn((bool,)) -> _` error: aborting due to previous error diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.rs b/src/test/ui/generator/type-mismatch-signature-deduction.rs index 7774ff48f56b7..d1b16b6e10da0 100644 --- a/src/test/ui/generator/type-mismatch-signature-deduction.rs +++ b/src/test/ui/generator/type-mismatch-signature-deduction.rs @@ -2,8 +2,8 @@ use std::ops::Generator; -fn foo() -> impl Generator { //~ ERROR type mismatch - || { +fn foo() -> impl Generator { + || { //~ ERROR type mismatch if false { return Ok(6); } diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.stderr b/src/test/ui/generator/type-mismatch-signature-deduction.stderr index 3f1f33a3b123f..3e78e5b53ba1f 100644 --- a/src/test/ui/generator/type-mismatch-signature-deduction.stderr +++ b/src/test/ui/generator/type-mismatch-signature-deduction.stderr @@ -13,13 +13,19 @@ LL | return Ok(6); | ^^^^^ error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:6:5: 14:6] as Generator>::Return == i32` - --> $DIR/type-mismatch-signature-deduction.rs:5:13 + --> $DIR/type-mismatch-signature-deduction.rs:6:5 | -LL | fn foo() -> impl Generator { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found enum `Result` +LL | / || { +LL | | if false { +LL | | return Ok(6); +LL | | } +... | +LL | | 5 +LL | | } + | |_____^ expected enum `Result`, found `i32` | - = note: expected type `i32` - found enum `Result<{integer}, _>` + = note: expected enum `Result<{integer}, _>` + found type `i32` error: aborting due to 2 previous errors diff --git a/src/test/ui/generic-associated-types/issue-87258_a.rs b/src/test/ui/generic-associated-types/issue-87258_a.rs index d9d17751fa6e2..16b56db75debc 100644 --- a/src/test/ui/generic-associated-types/issue-87258_a.rs +++ b/src/test/ui/generic-associated-types/issue-87258_a.rs @@ -16,7 +16,8 @@ pub trait Trait2 { impl<'c, S: Trait2> Trait2 for &'c mut S { type FooFuture<'a> = impl Trait1; - fn foo<'a>() -> Self::FooFuture<'a> { //~ ERROR + //~^ ERROR could not find defining uses + fn foo<'a>() -> Self::FooFuture<'a> { Struct(unimplemented!()) } } diff --git a/src/test/ui/generic-associated-types/issue-87258_a.stderr b/src/test/ui/generic-associated-types/issue-87258_a.stderr index 93513a4563f07..25166a5f5e129 100644 --- a/src/test/ui/generic-associated-types/issue-87258_a.stderr +++ b/src/test/ui/generic-associated-types/issue-87258_a.stderr @@ -1,11 +1,8 @@ -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/issue-87258_a.rs:19:21 +error: could not find defining uses + --> $DIR/issue-87258_a.rs:18:26 | -LL | fn foo<'a>() -> Self::FooFuture<'a> { - | ^^^^^^^^^^^^^^^^^^^ - | - = note: hidden type `Struct<'_>` captures lifetime '_#7r +LL | type FooFuture<'a> = impl Trait1; + | ^^^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/generic-associated-types/issue-87258_b.rs b/src/test/ui/generic-associated-types/issue-87258_b.rs index b29a978f517ff..30bdc29474eb6 100644 --- a/src/test/ui/generic-associated-types/issue-87258_b.rs +++ b/src/test/ui/generic-associated-types/issue-87258_b.rs @@ -15,10 +15,11 @@ pub trait Trait2 { } type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1; +//~^ ERROR could not find defining uses impl<'c, S: Trait2> Trait2 for &'c mut S { type FooFuture<'a> = Helper<'c, 'a, S>; - fn foo<'a>() -> Self::FooFuture<'a> { //~ ERROR + fn foo<'a>() -> Self::FooFuture<'a> { Struct(unimplemented!()) } } diff --git a/src/test/ui/generic-associated-types/issue-87258_b.stderr b/src/test/ui/generic-associated-types/issue-87258_b.stderr index e077a423400df..ea30117201e0f 100644 --- a/src/test/ui/generic-associated-types/issue-87258_b.stderr +++ b/src/test/ui/generic-associated-types/issue-87258_b.stderr @@ -1,11 +1,8 @@ -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/issue-87258_b.rs:21:21 +error: could not find defining uses + --> $DIR/issue-87258_b.rs:17:49 | -LL | fn foo<'a>() -> Self::FooFuture<'a> { - | ^^^^^^^^^^^^^^^^^^^ - | - = note: hidden type `Struct<'_>` captures lifetime '_#7r +LL | type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1; + | ^^^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/generic-associated-types/issue-88595.stderr b/src/test/ui/generic-associated-types/issue-88595.stderr index cb462871ccd32..6c3a75c85714a 100644 --- a/src/test/ui/generic-associated-types/issue-88595.stderr +++ b/src/test/ui/generic-associated-types/issue-88595.stderr @@ -16,10 +16,10 @@ LL | type B<'b> = impl Clone; | ^^ error: non-defining opaque type use in defining scope - --> $DIR/issue-88595.rs:23:23 + --> $DIR/issue-88595.rs:23:35 | LL | fn a(&'a self) -> Self::B<'a> {} - | ^^^^^^^^^^^ + | ^^ | note: lifetime used multiple times --> $DIR/issue-88595.rs:18:6 diff --git a/src/test/ui/generic-associated-types/issue-92096.migrate.stderr b/src/test/ui/generic-associated-types/issue-92096.migrate.stderr index 72ade5774d749..f8c89829e1646 100644 --- a/src/test/ui/generic-associated-types/issue-92096.migrate.stderr +++ b/src/test/ui/generic-associated-types/issue-92096.migrate.stderr @@ -1,18 +1,20 @@ error[E0311]: the parameter type `C` may not live long enough - --> $DIR/issue-92096.rs:20:33 + --> $DIR/issue-92096.rs:24:5 | LL | fn call_connect(c: &'_ C) -> impl '_ + Future + Send - | - ^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds - | | - | help: consider adding an explicit lifetime bound...: `C: 'a` + | - help: consider adding an explicit lifetime bound...: `C: 'a` +... +LL | async move { c.connect().await } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds error[E0311]: the parameter type `C` may not live long enough - --> $DIR/issue-92096.rs:20:33 + --> $DIR/issue-92096.rs:24:5 | LL | fn call_connect(c: &'_ C) -> impl '_ + Future + Send - | - ^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds - | | - | help: consider adding an explicit lifetime bound...: `C: 'a` + | - help: consider adding an explicit lifetime bound...: `C: 'a` +... +LL | async move { c.connect().await } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds error: aborting due to 2 previous errors diff --git a/src/test/ui/generic-associated-types/issue-92096.rs b/src/test/ui/generic-associated-types/issue-92096.rs index 066132a5d98bb..2bc1af5506ffd 100644 --- a/src/test/ui/generic-associated-types/issue-92096.rs +++ b/src/test/ui/generic-associated-types/issue-92096.rs @@ -18,12 +18,12 @@ trait Client { } fn call_connect(c: &'_ C) -> impl '_ + Future + Send -//[migrate]~^ ERROR the parameter -//[migrate]~| ERROR the parameter where C: Client + Send + Sync, { async move { c.connect().await } + //[migrate]~^ ERROR the parameter + //[migrate]~| ERROR the parameter } fn main() {} diff --git a/src/test/ui/impl-trait/auto-trait-leak.rs b/src/test/ui/impl-trait/auto-trait-leak.rs index c2fbbf94fd666..d2452abab0254 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.rs +++ b/src/test/ui/impl-trait/auto-trait-leak.rs @@ -11,6 +11,7 @@ fn main() { // return type, which can't depend on the obligation. fn cycle1() -> impl Clone { //~^ ERROR cycle detected + //~| ERROR cycle detected send(cycle2().clone()); Rc::new(Cell::new(5)) diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr index 634ff14869eb4..14db864f1c28a 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak.stderr @@ -30,47 +30,129 @@ note: ...which requires building MIR for `cycle1`... LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires type-checking `cycle1`... - --> $DIR/auto-trait-leak.rs:14:5 + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires computing type of `cycle2::{opaque#0}`... + --> $DIR/auto-trait-leak.rs:20:16 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^ +note: ...which requires borrow-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:20:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing `cycle2`... + --> $DIR/auto-trait-leak.rs:20:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing MIR for `cycle2`... + --> $DIR/auto-trait-leak.rs:20:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires unsafety-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:20:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for `cycle2`... + --> $DIR/auto-trait-leak.rs:20:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:20:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/auto-trait-leak.rs:1:1 + | +LL | / use std::cell::Cell; +LL | | use std::rc::Rc; +LL | | +LL | | fn send(_: T) {} +... | +LL | | Rc::new(String::from("foo")) +LL | | } + | |_^ + +error[E0391]: cycle detected when computing type of `cycle1::{opaque#0}` + --> $DIR/auto-trait-leak.rs:12:16 | -LL | send(cycle2().clone()); - | ^^^^ - = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`... +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^ + | +note: ...which requires borrow-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing MIR for `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires unsafety-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires computing type of `cycle2::{opaque#0}`... - --> $DIR/auto-trait-leak.rs:19:16 + --> $DIR/auto-trait-leak.rs:20:16 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^ note: ...which requires borrow-checking `cycle2`... - --> $DIR/auto-trait-leak.rs:19:1 + --> $DIR/auto-trait-leak.rs:20:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires processing `cycle2`... - --> $DIR/auto-trait-leak.rs:19:1 + --> $DIR/auto-trait-leak.rs:20:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires processing MIR for `cycle2`... - --> $DIR/auto-trait-leak.rs:19:1 + --> $DIR/auto-trait-leak.rs:20:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires unsafety-checking `cycle2`... - --> $DIR/auto-trait-leak.rs:19:1 + --> $DIR/auto-trait-leak.rs:20:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires building MIR for `cycle2`... - --> $DIR/auto-trait-leak.rs:19:1 + --> $DIR/auto-trait-leak.rs:20:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires type-checking `cycle2`... - --> $DIR/auto-trait-leak.rs:20:5 + --> $DIR/auto-trait-leak.rs:20:1 | -LL | send(cycle1().clone()); - | ^^^^ - = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`... +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle note: cycle used when checking item types in top-level module --> $DIR/auto-trait-leak.rs:1:1 @@ -84,6 +166,6 @@ LL | | Rc::new(String::from("foo")) LL | | } | |_^ -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/impl-trait/bound-normalization-fail.rs b/src/test/ui/impl-trait/bound-normalization-fail.rs index 8ec06e534d143..20ddad0547ef2 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.rs +++ b/src/test/ui/impl-trait/bound-normalization-fail.rs @@ -23,8 +23,8 @@ mod impl_trait { /// `T::Assoc` can't be normalized any further here. fn foo_fail() -> impl FooLike { - //~^ ERROR: type mismatch Foo(()) + //~^ ERROR: type mismatch } } @@ -39,9 +39,9 @@ mod lifetimes { /// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further. fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { - //~^ ERROR: type mismatch - //~^^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope + //~^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope Foo(()) + //~^ ERROR: type mismatch } } diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr index afa21c1a858a2..01fb853e1d1f7 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.stderr +++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr @@ -1,16 +1,16 @@ error[E0271]: type mismatch resolving ` as FooLike>::Output == ::Assoc` - --> $DIR/bound-normalization-fail.rs:25:32 + --> $DIR/bound-normalization-fail.rs:26:9 | -LL | fn foo_fail() -> impl FooLike { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as FooLike>::Output == ::Assoc` +LL | Foo(()) + | ^^^^^^^ type mismatch resolving ` as FooLike>::Output == ::Assoc` | -note: expected this to be `::Assoc` +note: expected this to be `()` --> $DIR/bound-normalization-fail.rs:14:19 | LL | type Output = T; | ^ - = note: expected associated type `::Assoc` - found unit type `()` + = note: expected unit type `()` + found associated type `::Assoc` help: consider constraining the associated type `::Assoc` to `()` | LL | fn foo_fail>() -> impl FooLike { @@ -23,18 +23,18 @@ LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0271]: type mismatch resolving ` as FooLike>::Output == >::Assoc` - --> $DIR/bound-normalization-fail.rs:41:41 + --> $DIR/bound-normalization-fail.rs:43:9 | -LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as FooLike>::Output == >::Assoc` +LL | Foo(()) + | ^^^^^^^ type mismatch resolving ` as FooLike>::Output == >::Assoc` | -note: expected this to be `>::Assoc` +note: expected this to be `()` --> $DIR/bound-normalization-fail.rs:14:19 | LL | type Output = T; | ^ - = note: expected associated type `>::Assoc` - found unit type `()` + = note: expected unit type `()` + found associated type `>::Assoc` help: consider constraining the associated type `>::Assoc` to `()` | LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike { diff --git a/src/test/ui/impl-trait/does-not-live-long-enough.stderr b/src/test/ui/impl-trait/does-not-live-long-enough.stderr index f4bd0fde3b6cb..750687e232228 100644 --- a/src/test/ui/impl-trait/does-not-live-long-enough.stderr +++ b/src/test/ui/impl-trait/does-not-live-long-enough.stderr @@ -7,10 +7,10 @@ LL | self.data.iter().filter(|s| s.starts_with(prefix)).map(|s| s.as_ref | may outlive borrowed value `prefix` | note: closure is returned here - --> $DIR/does-not-live-long-enough.rs:5:55 + --> $DIR/does-not-live-long-enough.rs:6:9 | -LL | fn started_with<'a>(&'a self, prefix: &'a str) -> impl Iterator { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | self.data.iter().filter(|s| s.starts_with(prefix)).map(|s| s.as_ref()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: to force the closure to take ownership of `prefix` (and any other referenced variables), use the `move` keyword | LL | self.data.iter().filter(move |s| s.starts_with(prefix)).map(|s| s.as_ref()) diff --git a/src/test/ui/impl-trait/equality.rs b/src/test/ui/impl-trait/equality.rs index 9610618ca11f6..59770c10da2b2 100644 --- a/src/test/ui/impl-trait/equality.rs +++ b/src/test/ui/impl-trait/equality.rs @@ -17,8 +17,8 @@ fn two(x: bool) -> impl Foo { //~| expected `i32`, found `u32` } -fn sum_to(n: u32) -> impl Foo { //~ ERROR type annotations needed - if n == 0 { +fn sum_to(n: u32) -> impl Foo { + if n == 0 { //~ ERROR type annotations needed 0 } else { n + sum_to(n - 1) diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index d9819484a9612..f79411c1003eb 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -11,20 +11,11 @@ LL | #![feature(specialization)] error[E0308]: mismatched types --> $DIR/equality.rs:15:5 | -LL | fn two(x: bool) -> impl Foo { - | -------- expected because this return type... -LL | if x { LL | return 1_i32; - | ----- ...is found to be `i32` here + | ----- type expected due to this LL | } LL | 0_u32 | ^^^^^ expected `i32`, found `u32` - | - = note: to return `impl Trait`, all returned values must be of the same type - = note: for information on `impl Trait`, see - = help: if the trait `Foo` were object safe, you could return a boxed trait object - = note: for information on trait objects, see - = help: you could instead create a new `enum` with a variant for each returned type error[E0277]: cannot add `impl Foo` to `u32` --> $DIR/equality.rs:24:11 @@ -35,10 +26,15 @@ LL | n + sum_to(n - 1) = help: the trait `Add` is not implemented for `u32` error[E0283]: type annotations needed - --> $DIR/equality.rs:20:22 - | -LL | fn sum_to(n: u32) -> impl Foo { - | ^^^^^^^^ cannot infer type for type `{integer}` + --> $DIR/equality.rs:21:5 + | +LL | / if n == 0 { +LL | | 0 +LL | | } else { +LL | | n + sum_to(n - 1) +LL | | +LL | | } + | |_____^ cannot infer type for type `{integer}` | = note: multiple `impl`s satisfying `{integer}: ToString` found in the `alloc` crate: - impl ToString for i8; diff --git a/src/test/ui/impl-trait/equality2.stderr b/src/test/ui/impl-trait/equality2.stderr index 46053c6e7c119..fd33fa7c674f1 100644 --- a/src/test/ui/impl-trait/equality2.stderr +++ b/src/test/ui/impl-trait/equality2.stderr @@ -15,9 +15,7 @@ LL | fn hide(x: T) -> impl Foo { | -------- the found opaque type ... LL | let _: u32 = hide(0_u32); - | --- ^^^^^^^^^^^ expected `u32`, found opaque type - | | - | expected due to this + | ^^^^^^^^^^^ expected `u32`, found opaque type | = note: expected type `u32` found opaque type `impl Foo` diff --git a/src/test/ui/impl-trait/fallback.rs b/src/test/ui/impl-trait/fallback.rs new file mode 100644 index 0000000000000..1e6eb5bb35588 --- /dev/null +++ b/src/test/ui/impl-trait/fallback.rs @@ -0,0 +1,9 @@ +// check-pass + +fn take_edge_counters( + x: &mut Option>, +) -> Option> { + x.take().map_or(None, |m| Some(m.into_iter())) +} + +fn main() {} diff --git a/src/test/ui/impl-trait/hidden-lifetimes.rs b/src/test/ui/impl-trait/hidden-lifetimes.rs index 2ee004a37a6fc..ae07c89276861 100644 --- a/src/test/ui/impl-trait/hidden-lifetimes.rs +++ b/src/test/ui/impl-trait/hidden-lifetimes.rs @@ -26,8 +26,8 @@ impl Swap for Rc> { // Here we are hiding `'b` making the caller believe that `&'a mut &'s T` and // `&'a mut &'l T` are the same type. fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { - //~^ ERROR hidden type x + //~^ ERROR hidden type } fn dangle_ref() -> &'static [i32; 3] { @@ -43,8 +43,8 @@ fn dangle_ref() -> &'static [i32; 3] { // This is different to the previous example because the concrete return type // only has a single lifetime. fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a { - //~^ ERROR hidden type x + //~^ ERROR hidden type } fn dangle_rc_refcell() -> &'static [i32; 3] { diff --git a/src/test/ui/impl-trait/hidden-lifetimes.stderr b/src/test/ui/impl-trait/hidden-lifetimes.stderr index c6d11293eec53..97652f5462ef0 100644 --- a/src/test/ui/impl-trait/hidden-lifetimes.stderr +++ b/src/test/ui/impl-trait/hidden-lifetimes.stderr @@ -1,10 +1,10 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/hidden-lifetimes.rs:28:54 + --> $DIR/hidden-lifetimes.rs:29:5 | LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { - | -- ^^^^^^^^^^^^^^ - | | - | hidden type `&'a mut &'b T` captures the lifetime `'b` as defined here + | -- hidden type `&'a mut &'b T` captures the lifetime `'b` as defined here +LL | x + | ^ | help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound | @@ -12,12 +12,12 @@ LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a + 'b { | ++++ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/hidden-lifetimes.rs:45:70 + --> $DIR/hidden-lifetimes.rs:46:5 | LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a { - | -- ^^^^^^^^^^^^^^ - | | - | hidden type `Rc>` captures the lifetime `'b` as defined here + | -- hidden type `Rc>` captures the lifetime `'b` as defined here +LL | x + | ^ | help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound | diff --git a/src/test/ui/impl-trait/issue-55872-1.rs b/src/test/ui/impl-trait/issue-55872-1.rs index 46188636475db..7d29882995355 100644 --- a/src/test/ui/impl-trait/issue-55872-1.rs +++ b/src/test/ui/impl-trait/issue-55872-1.rs @@ -8,13 +8,13 @@ pub trait Bar { impl Bar for S { type E = impl Copy; + //~^ ERROR could not find defining uses 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] + //~^ ERROR impl has stricter requirements than trait (S::default(), T::default()) + //~^ 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] } } diff --git a/src/test/ui/impl-trait/issue-55872-1.stderr b/src/test/ui/impl-trait/issue-55872-1.stderr index 2d1142fd0c52c..95138d86743cc 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:12:15 + --> $DIR/issue-55872-1.rs:13:15 | 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:12:29 + --> $DIR/issue-55872-1.rs:15:9 | -LL | fn foo() -> Self::E { - | ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S` +LL | (S::default(), T::default()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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:12:29 + --> $DIR/issue-55872-1.rs:15:9 | -LL | fn foo() -> Self::E { - | ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T` +LL | (S::default(), T::default()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 @@ -31,18 +31,11 @@ help: consider further restricting this bound 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:12:37 - | -LL | fn foo() -> Self::E { - | _____________________________________^ -LL | | -LL | | -LL | | -LL | | -LL | | (S::default(), T::default()) -LL | | } - | |_____^ +error: could not find defining uses + --> $DIR/issue-55872-1.rs:10:14 + | +LL | type E = impl Copy; + | ^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/impl-trait/issue-55872-2.rs b/src/test/ui/impl-trait/issue-55872-2.rs index a519397806e07..f0bc0b5272784 100644 --- a/src/test/ui/impl-trait/issue-55872-2.rs +++ b/src/test/ui/impl-trait/issue-55872-2.rs @@ -4,17 +4,16 @@ #![feature(type_alias_impl_trait)] pub trait Bar { - type E: Copy; + type E: Send; fn foo() -> Self::E; } impl Bar for S { - type E = impl std::marker::Copy; + type E = impl std::marker::Send; 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 async {} + //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias } } diff --git a/src/test/ui/impl-trait/issue-55872-2.stderr b/src/test/ui/impl-trait/issue-55872-2.stderr index 97545ba3d1124..71090bdbf8061 100644 --- a/src/test/ui/impl-trait/issue-55872-2.stderr +++ b/src/test/ui/impl-trait/issue-55872-2.stderr @@ -1,20 +1,8 @@ -error[E0277]: the trait bound `impl Future: Copy` is not satisfied - --> $DIR/issue-55872-2.rs:14:20 - | -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:14:28 + --> $DIR/issue-55872-2.rs:15:9 | -LL | fn foo() -> Self::E { - | ____________________________^ -LL | | -LL | | -LL | | async {} -LL | | } - | |_____^ +LL | async {} + | ^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/issue-55872-3.rs b/src/test/ui/impl-trait/issue-55872-3.rs new file mode 100644 index 0000000000000..70f3c3c737ac9 --- /dev/null +++ b/src/test/ui/impl-trait/issue-55872-3.rs @@ -0,0 +1,21 @@ +// edition:2018 +// ignore-compare-mode-chalk + +#![feature(type_alias_impl_trait)] + +pub trait Bar { + type E: Copy; + + fn foo() -> Self::E; +} + +impl Bar for S { + type E = impl std::marker::Copy; + //~^ ERROR could not find defining uses + fn foo() -> Self::E { + async {} + //~^ ERROR the trait bound `impl Future: Copy` is not satisfied [E0277] + } +} + +fn main() {} diff --git a/src/test/ui/impl-trait/issue-55872-3.stderr b/src/test/ui/impl-trait/issue-55872-3.stderr new file mode 100644 index 0000000000000..5ef0b02006a71 --- /dev/null +++ b/src/test/ui/impl-trait/issue-55872-3.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `impl Future: Copy` is not satisfied + --> $DIR/issue-55872-3.rs:16:9 + | +LL | async {} + | ^^^^^^^^ the trait `Copy` is not implemented for `impl Future` + +error: could not find defining uses + --> $DIR/issue-55872-3.rs:13:14 + | +LL | type E = impl std::marker::Copy; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/issue-55872.rs b/src/test/ui/impl-trait/issue-55872.rs index bbd940254178c..65874d22ac6f3 100644 --- a/src/test/ui/impl-trait/issue-55872.rs +++ b/src/test/ui/impl-trait/issue-55872.rs @@ -11,8 +11,8 @@ impl Bar for S { type E = impl Copy; 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 type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias } } diff --git a/src/test/ui/impl-trait/issue-55872.stderr b/src/test/ui/impl-trait/issue-55872.stderr index 60654ec34610f..7abcf6a059422 100644 --- a/src/test/ui/impl-trait/issue-55872.stderr +++ b/src/test/ui/impl-trait/issue-55872.stderr @@ -1,12 +1,8 @@ error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872.rs:13:28 + --> $DIR/issue-55872.rs:14:9 | -LL | fn foo() -> Self::E { - | ____________________________^ -LL | | -LL | | || () -LL | | } - | |_____^ +LL | || () + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/impl-trait/issue-72911.rs b/src/test/ui/impl-trait/issue-72911.rs index dee5a41f6de37..d556e968f34e5 100644 --- a/src/test/ui/impl-trait/issue-72911.rs +++ b/src/test/ui/impl-trait/issue-72911.rs @@ -5,7 +5,7 @@ pub struct Lint {} impl Lint {} pub fn gather_all() -> impl Iterator { - //~^ ERROR: cannot resolve opaque type + //~^ ERROR `()` is not an iterator lint_files().flat_map(|f| gather_from_file(&f)) } @@ -16,6 +16,7 @@ fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator fn lint_files() -> impl Iterator { //~^ ERROR: failed to resolve + //~| ERROR `()` is not an iterator unimplemented!() } diff --git a/src/test/ui/impl-trait/issue-72911.stderr b/src/test/ui/impl-trait/issue-72911.stderr index e57fbf104dc6f..51648e6154dc3 100644 --- a/src/test/ui/impl-trait/issue-72911.stderr +++ b/src/test/ui/impl-trait/issue-72911.stderr @@ -10,25 +10,23 @@ error[E0433]: failed to resolve: use of undeclared crate or module `foo` LL | fn lint_files() -> impl Iterator { | ^^^ use of undeclared crate or module `foo` -error[E0720]: cannot resolve opaque type +error[E0277]: `()` is not an iterator --> $DIR/issue-72911.rs:7:24 | LL | pub fn gather_all() -> impl Iterator { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive opaque type -LL | -LL | lint_files().flat_map(|f| gather_from_file(&f)) - | ----------------------------------------------- - | | - | returning here with type `FlatMap, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>` - | returning here with type `FlatMap, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>` -... -LL | fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator { - | -------------------------- returning this opaque type `FlatMap, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>` -... + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-72911.rs:17:20 + | LL | fn lint_files() -> impl Iterator { - | -------------------------------------- returning this opaque type `FlatMap, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0433, E0720. -For more information about an error, try `rustc --explain E0433`. +Some errors have detailed explanations: E0277, E0433. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/issues/issue-70877.rs b/src/test/ui/impl-trait/issues/issue-70877.rs index 853c2a82bede4..42e5436390cbc 100644 --- a/src/test/ui/impl-trait/issues/issue-70877.rs +++ b/src/test/ui/impl-trait/issues/issue-70877.rs @@ -1,10 +1,12 @@ #![feature(type_alias_impl_trait)] +// check-pass + type FooArg<'a> = &'a dyn ToString; type FooRet = impl std::fmt::Debug; type FooItem = Box FooRet>; -type Foo = impl Iterator; //~ ERROR: type mismatch +type Foo = impl Iterator; #[repr(C)] struct Bar(u8); diff --git a/src/test/ui/impl-trait/issues/issue-70877.stderr b/src/test/ui/impl-trait/issues/issue-70877.stderr deleted file mode 100644 index fe48e92da5eac..0000000000000 --- a/src/test/ui/impl-trait/issues/issue-70877.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0271]: type mismatch resolving `::Item == Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` - --> $DIR/issue-70877.rs:7:12 - | -LL | type FooRet = impl std::fmt::Debug; - | -------------------- the found opaque type -... -LL | type Foo = impl Iterator; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `::Item == Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` - | -note: expected this to be `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` - --> $DIR/issue-70877.rs:13:17 - | -LL | type Item = FooItem; - | ^^^^^^^ - = note: expected struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` - found struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> impl Debug + 'static)>` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/impl-trait/issues/issue-78722.rs b/src/test/ui/impl-trait/issues/issue-78722.rs index bdbd20f9d2b88..b13ab6bad7fbe 100644 --- a/src/test/ui/impl-trait/issues/issue-78722.rs +++ b/src/test/ui/impl-trait/issues/issue-78722.rs @@ -10,7 +10,8 @@ struct Bug { async {} } let f: F = async { 1 }; - //~^ ERROR mismatched types [E0308] + //~^ ERROR `async` blocks are not allowed in constants + //~| ERROR destructors cannot be evaluated at compile-time 1 }], } diff --git a/src/test/ui/impl-trait/issues/issue-78722.stderr b/src/test/ui/impl-trait/issues/issue-78722.stderr index 130678de2370c..975c771759f9b 100644 --- a/src/test/ui/impl-trait/issues/issue-78722.stderr +++ b/src/test/ui/impl-trait/issues/issue-78722.stderr @@ -1,23 +1,22 @@ -error[E0308]: mismatched types +error[E0658]: `async` blocks are not allowed in constants --> $DIR/issue-78722.rs:12:20 | -LL | type F = impl core::future::Future; - | -------------------------------------- the expected opaque type -... LL | let f: F = async { 1 }; - | - ^^^^^^^^^^^ expected opaque type, found a different opaque type - | | - | expected due to this - | - ::: $SRC_DIR/core/src/future/mod.rs:LL:COL + | ^^^^^^^^^^^ | -LL | pub const fn from_generator(gen: T) -> impl Future - | ------------------------------- the found opaque type + = note: see issue #85368 for more information + = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/issue-78722.rs:12:13 | - = note: expected opaque type `impl Future` - found opaque type `impl Future` - = note: distinct uses of `impl Trait` result in different opaque types +LL | let f: F = async { 1 }; + | ^ constants cannot evaluate destructors +... +LL | }], + | - value is dropped here -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0493, E0658. +For more information about an error, try `rustc --explain E0493`. diff --git a/src/test/ui/impl-trait/issues/issue-86201.rs b/src/test/ui/impl-trait/issues/issue-86201.rs index e3386d29def02..0786e66ca8b06 100644 --- a/src/test/ui/impl-trait/issues/issue-86201.rs +++ b/src/test/ui/impl-trait/issues/issue-86201.rs @@ -1,10 +1,10 @@ #![feature(unboxed_closures)] #![feature(type_alias_impl_trait)] +// check-pass + type FunType = impl Fn<()>; -//~^ ERROR could not find defining uses static STATIC_FN: FunType = some_fn; -//~^ ERROR mismatched types fn some_fn() {} diff --git a/src/test/ui/impl-trait/issues/issue-86201.stderr b/src/test/ui/impl-trait/issues/issue-86201.stderr deleted file mode 100644 index b1460096ded66..0000000000000 --- a/src/test/ui/impl-trait/issues/issue-86201.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/issue-86201.rs:6:29 - | -LL | type FunType = impl Fn<()>; - | ----------- the expected opaque type -LL | -LL | static STATIC_FN: FunType = some_fn; - | ^^^^^^^ expected opaque type, found fn item - | - = note: expected opaque type `impl Fn<()>` - found fn item `fn() {some_fn}` - -error: could not find defining uses - --> $DIR/issue-86201.rs:4:16 - | -LL | type FunType = impl Fn<()>; - | ^^^^^^^^^^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/impl-trait/lifetimes2.rs b/src/test/ui/impl-trait/lifetimes2.rs new file mode 100644 index 0000000000000..834f2dc6cb5b6 --- /dev/null +++ b/src/test/ui/impl-trait/lifetimes2.rs @@ -0,0 +1,10 @@ +// check-pass + +pub fn keys<'a>(x: &'a Result) -> impl std::fmt::Debug + 'a { + match x { + Ok(map) => Ok(map), + Err(map) => Err(map), + } +} + +fn main() {} diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs index 72e9d96da3677..f5aaf1185211b 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs +++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs @@ -8,7 +8,6 @@ impl Copy for CopyIfEq {} type E<'a, 'b> = impl Sized; fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { - //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds let v = CopyIfEq::<*mut _, *mut _>(&mut { x }, &mut y); // This assignment requires that `x` and `y` have the same type due to the @@ -21,6 +20,7 @@ fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { let _: &'b i32 = *u.0; } u.0 + //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds } fn main() {} diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr index 40bec0da2707d..b837b64110365 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr @@ -1,10 +1,11 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/error-handling-2.rs:10:60 + --> $DIR/error-handling-2.rs:22:5 | LL | fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { - | -- ^^^^^^^^^ - | | - | hidden type `*mut &'a i32` captures the lifetime `'a` as defined here + | -- hidden type `*mut &'a i32` captures the lifetime `'a` as defined here +... +LL | u.0 + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs index 3a97624647efd..c4b56cd62534f 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs @@ -14,7 +14,6 @@ struct Ordinary<'a>(&'a u8); // by both `'a` and `'b`. fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> -//~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds where 'a: 'e, 'b: 'd, @@ -27,6 +26,8 @@ where // 'a in ['d, 'e] // ``` if condition() { a } else { b } + //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds + //~| ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds } fn condition() -> bool { diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr index 32829a0a1b2fa..04a5d73e0d378 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr @@ -1,16 +1,31 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ordinary-bounds-unrelated.rs:16:74 + --> $DIR/ordinary-bounds-unrelated.rs:28:22 | LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> - | -- ^^^^^^^^^^^^^^^^^^ - | | - | hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here + | -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here +... +LL | if condition() { a } else { b } + | ^ | help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound | LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b | ++++ -error: aborting due to previous error +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ordinary-bounds-unrelated.rs:28:33 + | +LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + | -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here +... +LL | if condition() { a } else { b } + | ^ + | +help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound + | +LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b + | ++++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs index d4c60a4e89209..ff2832c8986e5 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs @@ -16,7 +16,6 @@ struct Ordinary<'a>(&'a u8); // consider the loans for both `'a` and `'b` alive. fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> -//~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds { // We return a value: // @@ -30,6 +29,8 @@ fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> // // We are forced to pick that '0 = 'e, because only 'e is outlived by *both* 'a and 'b. if condition() { a } else { b } + //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds + //~| ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds } fn condition() -> bool { diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr index 83ad23b253bb3..018ba3ea5f760 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr @@ -1,16 +1,31 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ordinary-bounds-unsuited.rs:18:62 + --> $DIR/ordinary-bounds-unsuited.rs:31:22 | LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> - | -- ^^^^^^^^^^^^^^^^^^ - | | - | hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here + | -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here +... +LL | if condition() { a } else { b } + | ^ | help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound | LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b | ++++ -error: aborting due to previous error +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ordinary-bounds-unsuited.rs:31:33 + | +LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + | -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here +... +LL | if condition() { a } else { b } + | ^ + | +help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound + | +LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b + | ++++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr index 2f6bd8ff377a5..eb38f84d4afec 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr @@ -1,8 +1,8 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/must_outlive_least_region_or_bound.rs:3:23 + --> $DIR/must_outlive_least_region_or_bound.rs:3:35 | LL | fn elided(x: &i32) -> impl Copy { x } - | ---- ^^^^^^^^^ + | ---- ^ | | | hidden type `&i32` captures the anonymous lifetime defined here | @@ -12,10 +12,10 @@ LL | fn elided(x: &i32) -> impl Copy + '_ { x } | ++++ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/must_outlive_least_region_or_bound.rs:6:32 + --> $DIR/must_outlive_least_region_or_bound.rs:6:44 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } - | -- ^^^^^^^^^ + | -- ^ | | | hidden type `&'a i32` captures the lifetime `'a` as defined here | @@ -67,12 +67,12 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } = help: consider replacing `'a` with `'static` error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/must_outlive_least_region_or_bound.rs:33:61 + --> $DIR/must_outlive_least_region_or_bound.rs:34:5 | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { - | -- ^^^^^^^^^^^^^^^^ - | | - | hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:35:5: 35:31]` captures the lifetime `'b` as defined here + | -- hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:34:5: 34:31]` captures the lifetime `'b` as defined here +LL | move |_| println!("{}", y) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound | @@ -80,10 +80,10 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32 | ++++ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:38:51 + --> $DIR/must_outlive_least_region_or_bound.rs:39:5 | -LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { - | ^^^^^^^^^^^^^^^^^^^^ +LL | x + | ^ | = help: consider adding an explicit lifetime bound `T: 'static`... diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs index 69d2843ff3f01..02ea0255912ab 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs @@ -31,13 +31,13 @@ fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } //~ ERRO // Tests that a closure type containing 'b cannot be returned from a type where // only 'a was expected. fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { - //~^ ERROR: captures lifetime that does not appear in bounds move |_| println!("{}", y) + //~^ ERROR: captures lifetime that does not appear in bounds } fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { - //~^ ERROR the parameter type `T` may not live long enough x + //~^ ERROR the parameter type `T` may not live long enough } fn main() {} diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 07ac0a8db35a9..77ba0bf908763 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -1,8 +1,8 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/must_outlive_least_region_or_bound.rs:3:23 + --> $DIR/must_outlive_least_region_or_bound.rs:3:35 | LL | fn elided(x: &i32) -> impl Copy { x } - | ---- ^^^^^^^^^ + | ---- ^ | | | hidden type `&i32` captures the anonymous lifetime defined here | @@ -12,10 +12,10 @@ LL | fn elided(x: &i32) -> impl Copy + '_ { x } | ++++ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/must_outlive_least_region_or_bound.rs:6:32 + --> $DIR/must_outlive_least_region_or_bound.rs:6:44 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } - | -- ^^^^^^^^^ + | -- ^ | | | hidden type `&'a i32` captures the lifetime `'a` as defined here | @@ -28,15 +28,10 @@ error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'sta --> $DIR/must_outlive_least_region_or_bound.rs:9:46 | LL | fn elided2(x: &i32) -> impl Copy + 'static { x } - | ---- ^ ...is used here... + | ---- ^ ...is used and required to live as long as `'static` here | | | this data with an anonymous lifetime `'_`... | -note: ...and is required to live as long as `'static` here - --> $DIR/must_outlive_least_region_or_bound.rs:9:24 - | -LL | fn elided2(x: &i32) -> impl Copy + 'static { x } - | ^^^^^^^^^^^^^^^^^^^ help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x` | LL | fn elided2(x: &i32) -> impl Copy + '_ { x } @@ -50,15 +45,10 @@ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime --> $DIR/must_outlive_least_region_or_bound.rs:11:55 | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } - | ------- ^ ...is used here... + | ------- ^ ...is used and required to live as long as `'static` here | | | this data with lifetime `'a`... | -note: ...and is required to live as long as `'static` here - --> $DIR/must_outlive_least_region_or_bound.rs:11:33 - | -LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } - | ^^^^^^^^^^^^^^^^^^^ help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x` | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x } @@ -69,10 +59,10 @@ LL | fn explicit2<'a>(x: &'static i32) -> impl Copy + 'static { x } | ~~~~~~~~~~~~ error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/must_outlive_least_region_or_bound.rs:13:24 + --> $DIR/must_outlive_least_region_or_bound.rs:13:41 | LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } - | ---- ^^^^^^^^^^^^^^ lifetime `'a` required + | ---- ^ lifetime `'a` required | | | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` @@ -95,13 +85,8 @@ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime --> $DIR/must_outlive_least_region_or_bound.rs:29:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } - | ------- this data with lifetime `'a`... ^ ...is used here... - | -note: ...and is required to live as long as `'static` here - --> $DIR/must_outlive_least_region_or_bound.rs:29:34 + | ------- this data with lifetime `'a`... ^ ...is used and required to live as long as `'static` here | -LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x` | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x } @@ -112,12 +97,12 @@ LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x | ~~~~~~~~~~~~ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/must_outlive_least_region_or_bound.rs:33:61 + --> $DIR/must_outlive_least_region_or_bound.rs:34:5 | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { - | -- ^^^^^^^^^^^^^^^^ - | | - | hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:35:5: 35:31]` captures the lifetime `'b` as defined here + | -- hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:34:5: 34:31]` captures the lifetime `'b` as defined here +LL | move |_| println!("{}", y) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound | @@ -125,12 +110,12 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32 | ++++ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:38:51 + --> $DIR/must_outlive_least_region_or_bound.rs:39:5 | LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { - | -- ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds - | | - | help: consider adding an explicit lifetime bound...: `T: 'static +` + | -- help: consider adding an explicit lifetime bound...: `T: 'static +` +LL | x + | ^ ...so that the type `T` will meet its required lifetime bounds error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/must_outlive_least_region_or_bound.rs:16:50 diff --git a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr index 357166d112377..4b4116887dc27 100644 --- a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr +++ b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr @@ -1,47 +1,20 @@ error[E0308]: mismatched types --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:36:5 | -LL | fn can() -> impl NotObjectSafe { - | ------------------ expected because this return type... -LL | if true { LL | return A; - | - ...is found to be `A` here + | - type expected due to this LL | } LL | B | ^ expected struct `A`, found struct `B` - | - = note: to return `impl Trait`, all returned values must be of the same type - = note: for information on `impl Trait`, see - = help: if the trait `NotObjectSafe` were object safe, you could return a boxed trait object - = note: for information on trait objects, see - = help: you could instead create a new `enum` with a variant for each returned type error[E0308]: mismatched types --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:43:5 | -LL | fn cat() -> impl ObjectSafe { - | --------------- expected because this return type... -LL | if true { LL | return A; - | - ...is found to be `A` here + | - type expected due to this LL | } LL | B | ^ expected struct `A`, found struct `B` - | - = note: to return `impl Trait`, all returned values must be of the same type - = note: for information on `impl Trait`, see - = note: for information on trait objects, see - = help: you could instead create a new `enum` with a variant for each returned type -help: you could change the return type to be a boxed trait object - | -LL | fn cat() -> Box { - | ~~~~~~~ + -help: if you change the return type to expect trait objects, box the returned expressions - | -LL ~ return Box::new(A); -LL | } -LL ~ Box::new(B) - | error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs index fa7664a83eee0..9f9a6c784e638 100644 --- a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs +++ b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs @@ -14,10 +14,10 @@ fn bar() -> impl std::fmt::Display { } fn baz() -> impl std::fmt::Display { - if false { + if false { //~ ERROR mismatched types return 0i32; } else { - 1u32 //~ ERROR mismatched types + 1u32 } } @@ -30,9 +30,9 @@ fn qux() -> impl std::fmt::Display { } fn bat() -> impl std::fmt::Display { - match 13 { + match 13 { //~ ERROR mismatched types 0 => return 0i32, - _ => 1u32, //~ ERROR mismatched types + _ => 1u32, } } @@ -45,12 +45,12 @@ fn can() -> impl std::fmt::Display { } fn cat() -> impl std::fmt::Display { - match 13 { + match 13 { //~ ERROR mismatched types 0 => { return 0i32; } _ => { - 1u32 //~ ERROR mismatched types + 1u32 } } } diff --git a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr index 970abad5c72e9..eb0d3a52a4eb7 100644 --- a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr +++ b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr @@ -1,83 +1,31 @@ error[E0308]: mismatched types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:5:5 | -LL | fn foo() -> impl std::fmt::Display { - | ---------------------- expected because this return type... -LL | if false { LL | return 0i32; - | ---- ...is found to be `i32` here + | ---- type expected due to this LL | } LL | 1u32 | ^^^^ expected `i32`, found `u32` - | - = note: to return `impl Trait`, all returned values must be of the same type - = note: for information on `impl Trait`, see - = note: for information on trait objects, see - = help: you could instead create a new `enum` with a variant for each returned type -help: you could change the return type to be a boxed trait object - | -LL | fn foo() -> Box { - | ~~~~~~~ + -help: if you change the return type to expect trait objects, box the returned expressions - | -LL ~ return Box::new(0i32); -LL | } -LL ~ Box::new(1u32) - | error[E0308]: mismatched types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:12:16 | -LL | fn bar() -> impl std::fmt::Display { - | ---------------------- expected because this return type... -LL | if false { LL | return 0i32; - | ---- ...is found to be `i32` here + | ---- type expected due to this LL | } else { LL | return 1u32; | ^^^^ expected `i32`, found `u32` - | - = note: to return `impl Trait`, all returned values must be of the same type - = note: for information on `impl Trait`, see - = note: for information on trait objects, see - = help: you could instead create a new `enum` with a variant for each returned type -help: you could change the return type to be a boxed trait object - | -LL | fn bar() -> Box { - | ~~~~~~~ + -help: if you change the return type to expect trait objects, box the returned expressions - | -LL ~ return Box::new(0i32); -LL | } else { -LL ~ return Box::new(1u32); - | error[E0308]: mismatched types - --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:20:9 - | -LL | fn baz() -> impl std::fmt::Display { - | ---------------------- expected because this return type... -LL | if false { -LL | return 0i32; - | ---- ...is found to be `i32` here -LL | } else { -LL | 1u32 - | ^^^^ expected `i32`, found `u32` - | - = note: to return `impl Trait`, all returned values must be of the same type - = note: for information on `impl Trait`, see - = note: for information on trait objects, see - = help: you could instead create a new `enum` with a variant for each returned type -help: you could change the return type to be a boxed trait object - | -LL | fn baz() -> Box { - | ~~~~~~~ + -help: if you change the return type to expect trait objects, box the returned expressions - | -LL ~ return Box::new(0i32); -LL | } else { -LL ~ Box::new(1u32) + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:17:5 | +LL | / if false { +LL | | return 0i32; + | | ---- type expected due to this +LL | | } else { +LL | | 1u32 +LL | | } + | |_____^ expected `i32`, found `u32` error[E0308]: `if` and `else` have incompatible types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:28:9 @@ -103,87 +51,38 @@ LL ~ Box::new(1u32) | error[E0308]: mismatched types - --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:35:14 - | -LL | fn bat() -> impl std::fmt::Display { - | ---------------------- expected because this return type... -LL | match 13 { -LL | 0 => return 0i32, - | ---- ...is found to be `i32` here -LL | _ => 1u32, - | ^^^^ expected `i32`, found `u32` - | - = note: to return `impl Trait`, all returned values must be of the same type - = note: for information on `impl Trait`, see - = note: for information on trait objects, see - = help: you could instead create a new `enum` with a variant for each returned type -help: you could change the return type to be a boxed trait object - | -LL | fn bat() -> Box { - | ~~~~~~~ + -help: if you change the return type to expect trait objects, box the returned expressions - | -LL ~ 0 => return Box::new(0i32), -LL ~ _ => Box::new(1u32), + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:33:5 | +LL | / match 13 { +LL | | 0 => return 0i32, + | | ---- type expected due to this +LL | | _ => 1u32, +LL | | } + | |_____^ expected `i32`, found `u32` error[E0308]: mismatched types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:40:5 | -LL | fn can() -> impl std::fmt::Display { - | ---------------------- expected because this return type... LL | / match 13 { LL | | 0 => return 0i32, - | | ---- ...is found to be `i32` here + | | ---- type expected due to this LL | | 1 => 1u32, LL | | _ => 2u32, LL | | } | |_____^ expected `i32`, found `u32` - | - = note: to return `impl Trait`, all returned values must be of the same type - = note: for information on `impl Trait`, see - = note: for information on trait objects, see - = help: you could instead create a new `enum` with a variant for each returned type -help: you could change the return type to be a boxed trait object - | -LL | fn can() -> Box { - | ~~~~~~~ + -help: if you change the return type to expect trait objects, box the returned expressions - | -LL ~ Box::new(match 13 { -LL ~ 0 => return Box::new(0i32), -LL | 1 => 1u32, -LL | _ => 2u32, -LL ~ }) - | error[E0308]: mismatched types - --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:53:13 - | -LL | fn cat() -> impl std::fmt::Display { - | ---------------------- expected because this return type... -... -LL | return 0i32; - | ---- ...is found to be `i32` here -... -LL | 1u32 - | ^^^^ expected `i32`, found `u32` - | - = note: to return `impl Trait`, all returned values must be of the same type - = note: for information on `impl Trait`, see - = note: for information on trait objects, see - = help: you could instead create a new `enum` with a variant for each returned type -help: you could change the return type to be a boxed trait object - | -LL | fn cat() -> Box { - | ~~~~~~~ + -help: if you change the return type to expect trait objects, box the returned expressions - | -LL ~ return Box::new(0i32); -LL | } -LL | _ => { -LL ~ Box::new(1u32) + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:48:5 | +LL | / match 13 { +LL | | 0 => { +LL | | return 0i32; + | | ---- type expected due to this +LL | | } +... | +LL | | } +LL | | } + | |_____^ expected `i32`, found `u32` error[E0308]: `match` arms have incompatible types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:61:14 @@ -196,16 +95,6 @@ LL | | 1 => 1u32, LL | | _ => 2u32, LL | | } | |_____- `match` arms have incompatible types - | -help: you could change the return type to be a boxed trait object - | -LL | fn dog() -> Box { - | ~~~~~~~ + -help: if you change the return type to expect trait objects, box the returned expressions - | -LL ~ 0 => Box::new(0i32), -LL ~ 1 => Box::new(1u32), - | error[E0308]: `if` and `else` have incompatible types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:97:9 @@ -218,17 +107,6 @@ LL | | 1u32 | | ^^^^ expected `i32`, found `u32` LL | | } | |_____- `if` and `else` have incompatible types - | -help: you could change the return type to be a boxed trait object - | -LL | fn apt() -> Box { - | ~~~~~~~ + -help: if you change the return type to expect trait objects, box the returned expressions - | -LL ~ Box::new(0i32) -LL | } else { -LL ~ Box::new(1u32) - | error[E0746]: return type cannot have an unboxed trait object --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:66:13 diff --git a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs index b4fd6b3e74364..2e7cb21592cb0 100644 --- a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs +++ b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs @@ -11,8 +11,8 @@ pub trait Test {} impl Test for T where T: Super {} fn test() -> impl Test { - //~^ERROR type mismatch resolving `<() as Super>::Assoc == ()` () + //~^ERROR type mismatch resolving `<() as Super>::Assoc == ()` } fn main() { diff --git a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr index 65daabe419d3f..5ef1e9abef631 100644 --- a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr +++ b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr @@ -1,10 +1,10 @@ error[E0271]: type mismatch resolving `<() as Super>::Assoc == ()` - --> $DIR/projection-mismatch-in-impl-where-clause.rs:13:14 + --> $DIR/projection-mismatch-in-impl-where-clause.rs:14:5 | -LL | fn test() -> impl Test { - | ^^^^^^^^^ type mismatch resolving `<() as Super>::Assoc == ()` +LL | () + | ^^ type mismatch resolving `<() as Super>::Assoc == ()` | -note: expected this to be `()` +note: expected this to be `u8` --> $DIR/projection-mismatch-in-impl-where-clause.rs:6:18 | LL | type Assoc = u8; diff --git a/src/test/ui/impl-trait/question_mark.rs b/src/test/ui/impl-trait/question_mark.rs new file mode 100644 index 0000000000000..211f7972dbca8 --- /dev/null +++ b/src/test/ui/impl-trait/question_mark.rs @@ -0,0 +1,13 @@ +// check-pass + +fn foo() -> impl MyTrait { + panic!(); + MyStruct +} + +struct MyStruct; +trait MyTrait {} + +impl MyTrait for MyStruct {} + +fn main() {} diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs index 3cc537440977c..540a280f0a319 100644 --- a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs +++ b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs @@ -1,9 +1,8 @@ -// Test that an `impl Trait` type that expands to itself is an error. +// check-pass #![allow(unconditional_recursion)] fn test() -> impl Sized { - //~^ ERROR E0720 test() } diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr deleted file mode 100644 index 5a3027ec751a9..0000000000000 --- a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-direct.rs:5:14 - | -LL | fn test() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | test() - | ------ returning here with type `impl Sized` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0720`. diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs index e3c621f0c5742..ffc0cd9d10c34 100644 --- a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs +++ b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs @@ -5,7 +5,7 @@ #![allow(unconditional_recursion)] fn option(i: i32) -> impl Sized { - //~^ ERROR + //~^ ERROR cannot resolve opaque type if i < 0 { None } else { Some((option(i - 1), i)) } } diff --git a/src/test/ui/impl-trait/region-escape-via-bound.rs b/src/test/ui/impl-trait/region-escape-via-bound.rs index 29243699e44fd..18e3a5bcaa449 100644 --- a/src/test/ui/impl-trait/region-escape-via-bound.rs +++ b/src/test/ui/impl-trait/region-escape-via-bound.rs @@ -13,10 +13,10 @@ trait Trait<'a> { } impl Trait<'b> for Cell<&'a u32> { } fn foo(x: Cell<&'x u32>) -> impl Trait<'y> - //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds [E0700] where 'x: 'y { x + //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds [E0700] } fn main() { } diff --git a/src/test/ui/impl-trait/region-escape-via-bound.stderr b/src/test/ui/impl-trait/region-escape-via-bound.stderr index cf854f67d0456..690d049ec8f62 100644 --- a/src/test/ui/impl-trait/region-escape-via-bound.stderr +++ b/src/test/ui/impl-trait/region-escape-via-bound.stderr @@ -1,11 +1,11 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/region-escape-via-bound.rs:15:29 + --> $DIR/region-escape-via-bound.rs:18:5 | -LL | fn foo(x: Cell<&'x u32>) -> impl Trait<'y> - | ^^^^^^^^^^^^^^ -LL | LL | where 'x: 'y | -- hidden type `Cell<&'x u32>` captures the lifetime `'x` as defined here +LL | { +LL | x + | ^ | help: to declare that the `impl Trait` captures `'x`, you can add an explicit `'x` lifetime bound | diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.rs b/src/test/ui/impl-trait/static-return-lifetime-infered.rs index d792c6eafb32f..f940c1949d0b8 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.rs +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.rs @@ -4,14 +4,14 @@ struct A { impl A { fn iter_values_anon(&self) -> impl Iterator { + self.x.iter().map(|a| a.0) //~^ ERROR: captures lifetime that does not appear in bounds //~| ERROR: captures lifetime that does not appear in bounds - self.x.iter().map(|a| a.0) } fn iter_values<'a>(&'a self) -> impl Iterator { + self.x.iter().map(|a| a.0) //~^ ERROR: captures lifetime that does not appear in bounds //~| ERROR: captures lifetime that does not appear in bounds - self.x.iter().map(|a| a.0) } } diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index 7424da76182ab..bc8e39f9c504c 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -1,10 +1,10 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/static-return-lifetime-infered.rs:6:35 + --> $DIR/static-return-lifetime-infered.rs:7:9 | LL | fn iter_values_anon(&self) -> impl Iterator { - | ----- ^^^^^^^^^^^^^^^^^^^^^^^ - | | - | hidden type `Map, [closure@$DIR/static-return-lifetime-infered.rs:9:27: 9:34]>` captures the anonymous lifetime defined here + | ----- hidden type `Map, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:34]>` captures the anonymous lifetime defined here +LL | self.x.iter().map(|a| a.0) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound | @@ -12,12 +12,12 @@ LL | fn iter_values_anon(&self) -> impl Iterator + '_ { | ++++ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/static-return-lifetime-infered.rs:6:35 + --> $DIR/static-return-lifetime-infered.rs:7:9 | LL | fn iter_values_anon(&self) -> impl Iterator { - | ----- ^^^^^^^^^^^^^^^^^^^^^^^ - | | - | hidden type `Map, [closure@$DIR/static-return-lifetime-infered.rs:9:27: 9:34]>` captures the anonymous lifetime defined here + | ----- hidden type `Map, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:34]>` captures the anonymous lifetime defined here +LL | self.x.iter().map(|a| a.0) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound | @@ -25,12 +25,12 @@ LL | fn iter_values_anon(&self) -> impl Iterator + '_ { | ++++ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/static-return-lifetime-infered.rs:11:37 + --> $DIR/static-return-lifetime-infered.rs:12:9 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { - | -- ^^^^^^^^^^^^^^^^^^^^^^^ - | | - | hidden type `Map, [closure@$DIR/static-return-lifetime-infered.rs:14:27: 14:34]>` captures the lifetime `'a` as defined here + | -- hidden type `Map, [closure@$DIR/static-return-lifetime-infered.rs:12:27: 12:34]>` captures the lifetime `'a` as defined here +LL | self.x.iter().map(|a| a.0) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound | @@ -38,12 +38,12 @@ LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { | ++++ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/static-return-lifetime-infered.rs:11:37 + --> $DIR/static-return-lifetime-infered.rs:12:9 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { - | -- ^^^^^^^^^^^^^^^^^^^^^^^ - | | - | hidden type `Map, [closure@$DIR/static-return-lifetime-infered.rs:14:27: 14:34]>` captures the lifetime `'a` as defined here + | -- hidden type `Map, [closure@$DIR/static-return-lifetime-infered.rs:12:27: 12:34]>` captures the lifetime `'a` as defined here +LL | self.x.iter().map(|a| a.0) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound | diff --git a/src/test/ui/impl-trait/type_parameters_captured.nll.stderr b/src/test/ui/impl-trait/type_parameters_captured.nll.stderr index 039cb62f86656..e0b77544d439d 100644 --- a/src/test/ui/impl-trait/type_parameters_captured.nll.stderr +++ b/src/test/ui/impl-trait/type_parameters_captured.nll.stderr @@ -1,8 +1,8 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/type_parameters_captured.rs:7:20 + --> $DIR/type_parameters_captured.rs:8:5 | -LL | fn foo(x: T) -> impl Any + 'static { - | ^^^^^^^^^^^^^^^^^^ +LL | x + | ^ | = help: consider adding an explicit lifetime bound `T: 'static`... diff --git a/src/test/ui/impl-trait/type_parameters_captured.rs b/src/test/ui/impl-trait/type_parameters_captured.rs index 6c9c9d4a42af5..81ee7d3f8a561 100644 --- a/src/test/ui/impl-trait/type_parameters_captured.rs +++ b/src/test/ui/impl-trait/type_parameters_captured.rs @@ -5,8 +5,8 @@ impl Any for T {} // Check that type parameters are captured and not considered 'static fn foo(x: T) -> impl Any + 'static { - //~^ ERROR the parameter type `T` may not live long enough x + //~^ ERROR the parameter type `T` may not live long enough } fn main() {} diff --git a/src/test/ui/impl-trait/type_parameters_captured.stderr b/src/test/ui/impl-trait/type_parameters_captured.stderr index 40e50b9922f8d..c0de4f4b4a0c5 100644 --- a/src/test/ui/impl-trait/type_parameters_captured.stderr +++ b/src/test/ui/impl-trait/type_parameters_captured.stderr @@ -1,10 +1,10 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/type_parameters_captured.rs:7:20 + --> $DIR/type_parameters_captured.rs:8:5 | LL | fn foo(x: T) -> impl Any + 'static { - | - ^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds - | | - | help: consider adding an explicit lifetime bound...: `T: 'static` + | - help: consider adding an explicit lifetime bound...: `T: 'static` +LL | x + | ^ ...so that the type `T` will meet its required lifetime bounds error: aborting due to previous error diff --git a/src/test/ui/impl-trait/where-allowed-2.rs b/src/test/ui/impl-trait/where-allowed-2.rs index 462508f306ef3..d5a87b5d46834 100644 --- a/src/test/ui/impl-trait/where-allowed-2.rs +++ b/src/test/ui/impl-trait/where-allowed-2.rs @@ -1,8 +1,7 @@ -//! Ideally, these tests would go in `where-allowed.rs`, but we bail out -//! too early to display them. use std::fmt::Debug; -// Disallowed -fn in_adt_in_return() -> Vec { panic!() } //~ ERROR cannot resolve opaque type +// check-pass + +fn in_adt_in_return() -> Vec { panic!() } fn main() {} diff --git a/src/test/ui/impl-trait/where-allowed-2.stderr b/src/test/ui/impl-trait/where-allowed-2.stderr deleted file mode 100644 index b8e06725cbcdd..0000000000000 --- a/src/test/ui/impl-trait/where-allowed-2.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0720]: cannot resolve opaque type - --> $DIR/where-allowed-2.rs:6:30 - | -LL | fn in_adt_in_return() -> Vec { panic!() } - | ^^^^^^^^^^ -------- this returned value is of `!` type - | | - | cannot resolve opaque type - | - = help: this error will resolve once the item's body returns a concrete type - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0720`. diff --git a/src/test/ui/issues-71798.rs b/src/test/ui/issues-71798.rs index fecba721ac9fd..89e07037afd42 100644 --- a/src/test/ui/issues-71798.rs +++ b/src/test/ui/issues-71798.rs @@ -1,5 +1,6 @@ fn test_ref(x: &u32) -> impl std::future::Future + '_ { - *x //~^ ERROR `u32` is not a future + *x + //~^ ERROR `u32` is not a future } fn main() { diff --git a/src/test/ui/issues-71798.stderr b/src/test/ui/issues-71798.stderr index bc4dc9ebf9e00..1efa886436e0d 100644 --- a/src/test/ui/issues-71798.stderr +++ b/src/test/ui/issues-71798.stderr @@ -1,14 +1,14 @@ error[E0425]: cannot find value `u` in this scope - --> $DIR/issues-71798.rs:6:24 + --> $DIR/issues-71798.rs:7:24 | LL | let _ = test_ref & u; | ^ not found in this scope error[E0277]: `u32` is not a future - --> $DIR/issues-71798.rs:1:25 + --> $DIR/issues-71798.rs:2:5 | -LL | fn test_ref(x: &u32) -> impl std::future::Future + '_ { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `u32` is not a future +LL | *x + | ^^ `u32` is not a future | = help: the trait `Future` is not implemented for `u32` = note: u32 must be a future or must implement `IntoFuture` to be awaited diff --git a/src/test/ui/lang-items/lang-item-missing-generator.stderr b/src/test/ui/lang-items/lang-item-missing-generator.stderr index fa13bf0b12719..e5f26822f2670 100644 --- a/src/test/ui/lang-items/lang-item-missing-generator.stderr +++ b/src/test/ui/lang-items/lang-item-missing-generator.stderr @@ -1,8 +1,8 @@ error: requires `generator` lang_item - --> $DIR/lang-item-missing-generator.rs:15:17 + --> $DIR/lang-item-missing-generator.rs:15:22 | LL | pub fn abc() -> impl FnOnce(f32) { - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/lazy-type-alias-impl-trait/freeze_cycle.rs b/src/test/ui/lazy-type-alias-impl-trait/freeze_cycle.rs new file mode 100644 index 0000000000000..84bfa2d848755 --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/freeze_cycle.rs @@ -0,0 +1,46 @@ +// check-pass + +#![feature(gen_future, generator_trait, negative_impls, const_fn_trait_bound, const_impl_trait)] + +use std::ops::{Generator, GeneratorState}; +use std::task::{Poll, Context}; +use std::future::{Future}; +use std::ptr::NonNull; +use std::pin::Pin; + +fn main() {} + +#[derive(Debug, Copy, Clone)] +pub struct ResumeTy(NonNull>); + +unsafe impl Send for ResumeTy {} + +unsafe impl Sync for ResumeTy {} + +pub const fn from_generator(gen: T) -> impl Future +where + T: Generator, +{ + struct GenFuture>(T); + + // We rely on the fact that async/await futures are immovable in order to create + // self-referential borrows in the underlying generator. + impl> !Unpin for GenFuture {} + + impl> Future for GenFuture { + type Output = T::Return; + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + // SAFETY: Safe because we're !Unpin + !Drop, and this is just a field projection. + let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) }; + + // Resume the generator, turning the `&mut Context` into a `NonNull` raw pointer. The + // `.await` lowering will safely cast that back to a `&mut Context`. + match gen.resume(ResumeTy(NonNull::from(cx).cast::>())) { + GeneratorState::Yielded(()) => Poll::Pending, + GeneratorState::Complete(x) => Poll::Ready(x), + } + } + } + + GenFuture(gen) +} diff --git a/src/test/ui/lazy-type-alias-impl-trait/infer_cross_function.rs b/src/test/ui/lazy-type-alias-impl-trait/infer_cross_function.rs new file mode 100644 index 0000000000000..d07d732c78570 --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/infer_cross_function.rs @@ -0,0 +1,27 @@ +// check-pass + +fn main() {} + +trait Reader {} + +struct Unit(R); +struct ResDwarf(R); + +struct Context { + dwarf: ResDwarf, +} + +struct Range; + +struct ResUnit(R); + +impl Context { + fn find_dwarf_unit(&self, probe: u64) -> Option<&Unit> { + let x = self.find_units(probe); + None + } + + fn find_units(&self, probe: u64) -> impl Iterator> { + std::iter::empty() + } +} diff --git a/src/test/ui/lazy-type-alias-impl-trait/lifetime_inference.rs b/src/test/ui/lazy-type-alias-impl-trait/lifetime_inference.rs new file mode 100644 index 0000000000000..f75a88aa8f064 --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/lifetime_inference.rs @@ -0,0 +1,7 @@ +// check-pass + +fn main() {} + +fn nth(iter: &mut I, step: usize) -> impl FnMut() -> Option + '_ { + move || iter.nth(step) +} diff --git a/src/test/ui/lazy-type-alias-impl-trait/nested.rs b/src/test/ui/lazy-type-alias-impl-trait/nested.rs new file mode 100644 index 0000000000000..f8291112739c1 --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/nested.rs @@ -0,0 +1,23 @@ +// check-pass + +fn main() {} + +struct RawTableInner { + alloc: A, +} + +impl RawTableInner { + fn prepare_resize( + self, + ) -> ScopeGuard { + ScopeGuard { dropfn: move |self_| {}, value: self, } + } +} + +pub struct ScopeGuard +where + F: FnMut(&mut T), +{ + dropfn: F, + value: T, +} diff --git a/src/test/ui/lazy-type-alias-impl-trait/opaque_vs_opaque.rs b/src/test/ui/lazy-type-alias-impl-trait/opaque_vs_opaque.rs new file mode 100644 index 0000000000000..8d03b5158d662 --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/opaque_vs_opaque.rs @@ -0,0 +1,10 @@ +// check-pass + +fn main() {} + +fn filter_fold bool, FOLD: FnMut(Acc, T) -> Acc>( + mut predicate: PRED, + mut fold: FOLD, +) -> impl FnMut(Acc, T) -> Acc { + move |acc, item| if predicate(&item) { fold(acc, item) } else { acc } +} diff --git a/src/test/ui/lazy-type-alias-impl-trait/unsized_sized_opaque.rs b/src/test/ui/lazy-type-alias-impl-trait/unsized_sized_opaque.rs new file mode 100644 index 0000000000000..007101498238d --- /dev/null +++ b/src/test/ui/lazy-type-alias-impl-trait/unsized_sized_opaque.rs @@ -0,0 +1,16 @@ +// check-pass + +fn main() {} + +pub struct PairSlices<'a, 'b, T> { + pub(crate) a0: &'a mut [T], + pub(crate) a1: &'a mut [T], + pub(crate) b0: &'b [T], + pub(crate) b1: &'b [T], +} + +impl<'a, 'b, T> PairSlices<'a, 'b, T> { + pub fn remainder(self) -> impl Iterator { + IntoIterator::into_iter([self.b0, self.b1]) + } +} diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs index ea0d0ccbc5532..fd49b4842a74f 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs @@ -6,8 +6,8 @@ trait Future { use std::error::Error; fn foo() -> impl Future> { -//~^ ERROR not satisfied Ok(()) + //~^ ERROR not satisfied } fn main() {} diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr index ef1127c59ac4c..7f8384d7eca8d 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `Result<(), _>: Future` is not satisfied - --> $DIR/lifetime-elision-return-type-trait.rs:8:13 + --> $DIR/lifetime-elision-return-type-trait.rs:9:5 | -LL | fn foo() -> impl Future> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Future` is not implemented for `Result<(), _>` +LL | Ok(()) + | ^^^^^^ the trait `Future` is not implemented for `Result<(), _>` error: aborting due to previous error diff --git a/src/test/ui/never_type/feature-gate-never_type_fallback.rs b/src/test/ui/never_type/feature-gate-never_type_fallback.rs index 3b896ec9d70c2..7d02084118001 100644 --- a/src/test/ui/never_type/feature-gate-never_type_fallback.rs +++ b/src/test/ui/never_type/feature-gate-never_type_fallback.rs @@ -6,7 +6,8 @@ fn main() {} trait T {} -fn should_ret_unit() -> impl T { - //~^ ERROR the trait bound `(): T` is not satisfied - panic!() +fn should_ret_unit() { + foo(panic!()) //~ ERROR } + +fn foo(_: impl T) {} diff --git a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr index 670f76867ce45..54abed383000d 100644 --- a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr +++ b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr @@ -1,8 +1,14 @@ error[E0277]: the trait bound `(): T` is not satisfied - --> $DIR/feature-gate-never_type_fallback.rs:9:25 + --> $DIR/feature-gate-never_type_fallback.rs:10:5 | -LL | fn should_ret_unit() -> impl T { - | ^^^^^^ the trait `T` is not implemented for `()` +LL | foo(panic!()) + | ^^^ the trait `T` is not implemented for `()` + | +note: required by a bound in `foo` + --> $DIR/feature-gate-never_type_fallback.rs:13:16 + | +LL | fn foo(_: impl T) {} + | ^ required by this bound in `foo` error: aborting due to previous error diff --git a/src/test/ui/never_type/impl_trait_fallback.rs b/src/test/ui/never_type/impl_trait_fallback.rs new file mode 100644 index 0000000000000..cc9520c1b24c8 --- /dev/null +++ b/src/test/ui/never_type/impl_trait_fallback.rs @@ -0,0 +1,10 @@ +// check-pass + +fn main() {} + +trait T {} +impl T for () {} + +fn should_ret_unit() -> impl T { + panic!() +} diff --git a/src/test/ui/never_type/impl_trait_fallback2.rs b/src/test/ui/never_type/impl_trait_fallback2.rs new file mode 100644 index 0000000000000..f73d953bdbd0b --- /dev/null +++ b/src/test/ui/never_type/impl_trait_fallback2.rs @@ -0,0 +1,21 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +trait T {} +impl T for i32 {} + +fn should_ret_unit() -> impl T { + //~^ ERROR `(): T` is not satisfied + panic!() +} + +type Foo = impl T; + +fn a() -> Foo { + panic!() +} + +fn b() -> Foo { + 42 +} diff --git a/src/test/ui/never_type/impl_trait_fallback2.stderr b/src/test/ui/never_type/impl_trait_fallback2.stderr new file mode 100644 index 0000000000000..2f50b9d245900 --- /dev/null +++ b/src/test/ui/never_type/impl_trait_fallback2.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `(): T` is not satisfied + --> $DIR/impl_trait_fallback2.rs:8:25 + | +LL | fn should_ret_unit() -> impl T { + | ^^^^^^ the trait `T` is not implemented for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/never_type/impl_trait_fallback3.rs b/src/test/ui/never_type/impl_trait_fallback3.rs new file mode 100644 index 0000000000000..a44402a22b956 --- /dev/null +++ b/src/test/ui/never_type/impl_trait_fallback3.rs @@ -0,0 +1,15 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +trait T { + type Assoc; +} + +type Foo = impl T; +//~^ ERROR could not find defining uses + +fn a() -> Foo { + // This is not a defining use, it doesn't actually constrain the opaque type. + panic!() +} diff --git a/src/test/ui/never_type/impl_trait_fallback3.stderr b/src/test/ui/never_type/impl_trait_fallback3.stderr new file mode 100644 index 0000000000000..de04758a1e311 --- /dev/null +++ b/src/test/ui/never_type/impl_trait_fallback3.stderr @@ -0,0 +1,8 @@ +error: could not find defining uses + --> $DIR/impl_trait_fallback3.rs:9:12 + | +LL | type Foo = impl T; + | ^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/never_type/impl_trait_fallback4.rs b/src/test/ui/never_type/impl_trait_fallback4.rs new file mode 100644 index 0000000000000..fe62773fa02db --- /dev/null +++ b/src/test/ui/never_type/impl_trait_fallback4.rs @@ -0,0 +1,24 @@ +#![feature(type_alias_impl_trait)] + +trait T { + type Assoc: Cake; +} + +trait Cake: std::fmt::Display { + fn cake() -> Self; +} + +type Foo = impl T; + +fn foo() -> impl T { + //~^ ERROR `(): T` is not satisfied + panic!() +} + +fn a() -> Foo { + foo() +} + +fn main() { + println!("{}", ::Assoc::cake()); +} diff --git a/src/test/ui/never_type/impl_trait_fallback4.stderr b/src/test/ui/never_type/impl_trait_fallback4.stderr new file mode 100644 index 0000000000000..f2e216e9044c0 --- /dev/null +++ b/src/test/ui/never_type/impl_trait_fallback4.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `(): T` is not satisfied + --> $DIR/impl_trait_fallback4.rs:13:13 + | +LL | fn foo() -> impl T { + | ^^^^^^ the trait `T` is not implemented for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/nll/issue-52113.rs b/src/test/ui/nll/issue-52113.rs index 0d7ee0376924d..2f4cbf8322bbd 100644 --- a/src/test/ui/nll/issue-52113.rs +++ b/src/test/ui/nll/issue-52113.rs @@ -29,9 +29,9 @@ fn produce3<'a, 'b: 'a>(data: &'a mut Vec<&'a u32>, value: &'b u32) -> impl Bazi fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b { let x = move || { let value: &'a u32 = value; - data.push(value); + data.push(value); //~ ERROR lifetime may not live long enough }; - x //~ ERROR lifetime may not live long enough + x } fn main() {} diff --git a/src/test/ui/nll/issue-52113.stderr b/src/test/ui/nll/issue-52113.stderr index f70ae2edd7fac..d82affef26d2f 100644 --- a/src/test/ui/nll/issue-52113.stderr +++ b/src/test/ui/nll/issue-52113.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/issue-52113.rs:34:5 + --> $DIR/issue-52113.rs:32:9 | LL | fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/nll/issue-73159-rpit-static.rs b/src/test/ui/nll/issue-73159-rpit-static.rs index e29ba09b3694d..97dc016068bed 100644 --- a/src/test/ui/nll/issue-73159-rpit-static.rs +++ b/src/test/ui/nll/issue-73159-rpit-static.rs @@ -7,8 +7,8 @@ struct Foo<'a>(&'a [u8]); impl<'a> Foo<'a> { fn make_it(&self) -> impl Iterator { - //~^ ERROR: captures lifetime that does not appear in bounds self.0.iter().copied() + //~^ ERROR: captures lifetime that does not appear in bounds } } diff --git a/src/test/ui/nll/issue-73159-rpit-static.stderr b/src/test/ui/nll/issue-73159-rpit-static.stderr index 6c7cd0c825493..a3e9c0b44c210 100644 --- a/src/test/ui/nll/issue-73159-rpit-static.stderr +++ b/src/test/ui/nll/issue-73159-rpit-static.stderr @@ -1,10 +1,11 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/issue-73159-rpit-static.rs:9:26 + --> $DIR/issue-73159-rpit-static.rs:10:9 | LL | impl<'a> Foo<'a> { | -- hidden type `Copied>` captures the lifetime `'a` as defined here LL | fn make_it(&self) -> impl Iterator { - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | self.0.iter().copied() + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.rs b/src/test/ui/nll/ty-outlives/impl-trait-captures.rs index 8af23aad7261b..c04185d081424 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-captures.rs +++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.rs @@ -8,8 +8,8 @@ trait Foo<'a> { impl<'a, T> Foo<'a> for T { } fn foo<'a, T>(x: &T) -> impl Foo<'a> { -//~^ ERROR captures lifetime that does not appear in bounds x + //~^ ERROR captures lifetime that does not appear in bounds } fn main() {} diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr index 3e6fe789a8b55..96481810e33a2 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr +++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -1,5 +1,5 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/impl-trait-captures.rs:10:25 + --> $DIR/impl-trait-captures.rs:11:5 | LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { | -- ^^^^^^^^^^^^ diff --git a/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs b/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs index 0c7d8acb05223..3548ad03a7d3d 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs +++ b/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs @@ -5,11 +5,11 @@ use std::fmt::Debug; fn no_region<'a, T>(x: Box) -> impl Debug + 'a - //~^ ERROR the parameter type `T` may not live long enough [E0309] where T: Debug, { x + //~^ ERROR the parameter type `T` may not live long enough [E0309] } fn correct_region<'a, T>(x: Box) -> impl Debug + 'a @@ -20,11 +20,11 @@ where } fn wrong_region<'a, 'b, T>(x: Box) -> impl Debug + 'a - //~^ ERROR the parameter type `T` may not live long enough [E0309] where T: 'b + Debug, { x + //~^ ERROR the parameter type `T` may not live long enough [E0309] } fn outlives_region<'a, 'b, T>(x: Box) -> impl Debug + 'a diff --git a/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr index 053aef951f264..31ee540cce9f7 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr +++ b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr @@ -1,16 +1,16 @@ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/impl-trait-outlives.rs:7:35 + --> $DIR/impl-trait-outlives.rs:11:5 | -LL | fn no_region<'a, T>(x: Box) -> impl Debug + 'a - | ^^^^^^^^^^^^^^^ +LL | x + | ^ | = help: consider adding an explicit lifetime bound `T: 'a`... error[E0309]: the parameter type `T` may not live long enough - --> $DIR/impl-trait-outlives.rs:22:42 + --> $DIR/impl-trait-outlives.rs:26:5 | -LL | fn wrong_region<'a, 'b, T>(x: Box) -> impl Debug + 'a - | ^^^^^^^^^^^^^^^ +LL | x + | ^ | = help: consider adding an explicit lifetime bound `T: 'a`... diff --git a/src/test/ui/parser/fn-header-semantic-fail.rs b/src/test/ui/parser/fn-header-semantic-fail.rs index 91a63bafd99a9..cf5d3dab4aada 100644 --- a/src/test/ui/parser/fn-header-semantic-fail.rs +++ b/src/test/ui/parser/fn-header-semantic-fail.rs @@ -9,8 +9,9 @@ fn main() { unsafe fn ff2() {} // OK. const fn ff3() {} // OK. extern "C" fn ff4() {} // OK. - const async unsafe extern "C" fn ff5() {} // OK. + const async unsafe extern "C" fn ff5() {} //~^ ERROR functions cannot be both `const` and `async` + //~| ERROR cycle detected trait X { async fn ft1(); //~ ERROR functions in traits cannot be declared `async` @@ -26,15 +27,14 @@ fn main() { struct Y; impl X for Y { async fn ft1() {} //~ ERROR functions in traits cannot be declared `async` - //~^ ERROR method `ft1` has an incompatible type for trait unsafe fn ft2() {} // OK. const fn ft3() {} //~ ERROR functions in traits cannot be declared const extern "C" fn ft4() {} const async unsafe extern "C" fn ft5() {} //~^ ERROR functions in traits cannot be declared `async` //~| ERROR functions in traits cannot be declared const - //~| ERROR method `ft5` has an incompatible type for trait //~| ERROR functions cannot be both `const` and `async` + //~| ERROR cycle detected } impl Y { @@ -44,6 +44,7 @@ fn main() { extern "C" fn fi4() {} // OK. const async unsafe extern "C" fn fi5() {} //~^ ERROR functions cannot be both `const` and `async` + //~| ERROR cycle detected } extern "C" { diff --git a/src/test/ui/parser/fn-header-semantic-fail.stderr b/src/test/ui/parser/fn-header-semantic-fail.stderr index 8eaba559a6240..1d7460b8d3605 100644 --- a/src/test/ui/parser/fn-header-semantic-fail.stderr +++ b/src/test/ui/parser/fn-header-semantic-fail.stderr @@ -1,14 +1,14 @@ error: functions cannot be both `const` and `async` --> $DIR/fn-header-semantic-fail.rs:12:5 | -LL | const async unsafe extern "C" fn ff5() {} // OK. +LL | const async unsafe extern "C" fn ff5() {} | ^^^^^-^^^^^------------------------------ | | | | | `async` because of this | `const` because of this error[E0706]: functions in traits cannot be declared `async` - --> $DIR/fn-header-semantic-fail.rs:16:9 + --> $DIR/fn-header-semantic-fail.rs:17:9 | LL | async fn ft1(); | -----^^^^^^^^^^ @@ -19,19 +19,19 @@ LL | async fn ft1(); = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait error[E0379]: functions in traits cannot be declared const - --> $DIR/fn-header-semantic-fail.rs:18:9 + --> $DIR/fn-header-semantic-fail.rs:19:9 | LL | const fn ft3(); | ^^^^^ functions in traits cannot be const error[E0379]: functions in traits cannot be declared const - --> $DIR/fn-header-semantic-fail.rs:20:9 + --> $DIR/fn-header-semantic-fail.rs:21:9 | LL | const async unsafe extern "C" fn ft5(); | ^^^^^ functions in traits cannot be const error[E0706]: functions in traits cannot be declared `async` - --> $DIR/fn-header-semantic-fail.rs:20:9 + --> $DIR/fn-header-semantic-fail.rs:21:9 | LL | const async unsafe extern "C" fn ft5(); | ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -42,7 +42,7 @@ LL | const async unsafe extern "C" fn ft5(); = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait error: functions cannot be both `const` and `async` - --> $DIR/fn-header-semantic-fail.rs:20:9 + --> $DIR/fn-header-semantic-fail.rs:21:9 | LL | const async unsafe extern "C" fn ft5(); | ^^^^^-^^^^^---------------------------- @@ -51,7 +51,7 @@ LL | const async unsafe extern "C" fn ft5(); | `const` because of this error[E0706]: functions in traits cannot be declared `async` - --> $DIR/fn-header-semantic-fail.rs:28:9 + --> $DIR/fn-header-semantic-fail.rs:29:9 | LL | async fn ft1() {} | -----^^^^^^^^^^^^ @@ -103,7 +103,7 @@ LL | const async unsafe extern "C" fn fi5() {} | `const` because of this error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:50:18 + --> $DIR/fn-header-semantic-fail.rs:51:18 | LL | extern "C" { | ---------- in this `extern` block @@ -116,7 +116,7 @@ LL | fn fe1(); | ~~ error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:51:19 + --> $DIR/fn-header-semantic-fail.rs:52:19 | LL | extern "C" { | ---------- in this `extern` block @@ -130,7 +130,7 @@ LL | fn fe2(); | ~~ error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:52:18 + --> $DIR/fn-header-semantic-fail.rs:53:18 | LL | extern "C" { | ---------- in this `extern` block @@ -144,7 +144,7 @@ LL | fn fe3(); | ~~ error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:53:23 + --> $DIR/fn-header-semantic-fail.rs:54:23 | LL | extern "C" { | ---------- in this `extern` block @@ -158,7 +158,7 @@ LL | fn fe4(); | ~~ error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:54:42 + --> $DIR/fn-header-semantic-fail.rs:55:42 | LL | extern "C" { | ---------- in this `extern` block @@ -172,7 +172,7 @@ LL | fn fe5(); | ~~ error: functions cannot be both `const` and `async` - --> $DIR/fn-header-semantic-fail.rs:54:9 + --> $DIR/fn-header-semantic-fail.rs:55:9 | LL | const async unsafe extern "C" fn fe5(); | ^^^^^-^^^^^---------------------------- @@ -180,43 +180,115 @@ LL | const async unsafe extern "C" fn fe5(); | | `async` because of this | `const` because of this -error[E0053]: method `ft1` has an incompatible type for trait - --> $DIR/fn-header-semantic-fail.rs:28:24 +error[E0391]: cycle detected when computing type of `main::ff5::{opaque#0}` + --> $DIR/fn-header-semantic-fail.rs:12:44 | -LL | async fn ft1() {} - | ^ - | | - | checked the `Output` of this `async fn`, found opaque type - | expected `()`, found opaque type +LL | const async unsafe extern "C" fn ff5() {} + | ^ | - = note: while checking the return type of the `async fn` -note: type in trait - --> $DIR/fn-header-semantic-fail.rs:16:23 +note: ...which requires borrow-checking `main::ff5`... + --> $DIR/fn-header-semantic-fail.rs:12:5 | -LL | async fn ft1(); - | ^ - = note: expected fn pointer `fn()` - found fn pointer `fn() -> impl Future` +LL | const async unsafe extern "C" fn ff5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing `main::ff5`... + --> $DIR/fn-header-semantic-fail.rs:12:5 + | +LL | const async unsafe extern "C" fn ff5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const checking `main::ff5`... + --> $DIR/fn-header-semantic-fail.rs:12:5 + | +LL | const async unsafe extern "C" fn ff5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires computing whether `impl core::future::future::Future` is freeze... + = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future: core::marker::Freeze`... + = note: ...which again requires computing type of `main::ff5::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/fn-header-semantic-fail.rs:5:1 + | +LL | / #![feature(const_extern_fn)] +LL | | +LL | | fn main() { +LL | | async fn ff1() {} // OK. +... | +LL | | } +LL | | } + | |_^ -error[E0053]: method `ft5` has an incompatible type for trait +error[E0391]: cycle detected when computing type of `main::::ft5::{opaque#0}` --> $DIR/fn-header-semantic-fail.rs:33:48 | LL | const async unsafe extern "C" fn ft5() {} | ^ - | | - | checked the `Output` of this `async fn`, found opaque type - | expected `()`, found opaque type | - = note: while checking the return type of the `async fn` -note: type in trait - --> $DIR/fn-header-semantic-fail.rs:20:47 +note: ...which requires borrow-checking `main::::ft5`... + --> $DIR/fn-header-semantic-fail.rs:33:9 | -LL | const async unsafe extern "C" fn ft5(); - | ^ - = note: expected fn pointer `unsafe extern "C" fn()` - found fn pointer `unsafe extern "C" fn() -> impl Future` +LL | const async unsafe extern "C" fn ft5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing `main::::ft5`... + --> $DIR/fn-header-semantic-fail.rs:33:9 + | +LL | const async unsafe extern "C" fn ft5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const checking `main::::ft5`... + --> $DIR/fn-header-semantic-fail.rs:33:9 + | +LL | const async unsafe extern "C" fn ft5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires computing whether `impl core::future::future::Future` is freeze... + = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future: core::marker::Freeze`... + = note: ...which again requires computing type of `main::::ft5::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/fn-header-semantic-fail.rs:5:1 + | +LL | / #![feature(const_extern_fn)] +LL | | +LL | | fn main() { +LL | | async fn ff1() {} // OK. +... | +LL | | } +LL | | } + | |_^ + +error[E0391]: cycle detected when computing type of `main::::fi5::{opaque#0}` + --> $DIR/fn-header-semantic-fail.rs:45:48 + | +LL | const async unsafe extern "C" fn fi5() {} + | ^ + | +note: ...which requires borrow-checking `main::::fi5`... + --> $DIR/fn-header-semantic-fail.rs:45:9 + | +LL | const async unsafe extern "C" fn fi5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing `main::::fi5`... + --> $DIR/fn-header-semantic-fail.rs:45:9 + | +LL | const async unsafe extern "C" fn fi5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const checking `main::::fi5`... + --> $DIR/fn-header-semantic-fail.rs:45:9 + | +LL | const async unsafe extern "C" fn fi5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires computing whether `impl core::future::future::Future` is freeze... + = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future: core::marker::Freeze`... + = note: ...which again requires computing type of `main::::fi5::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/fn-header-semantic-fail.rs:5:1 + | +LL | / #![feature(const_extern_fn)] +LL | | +LL | | fn main() { +LL | | async fn ff1() {} // OK. +... | +LL | | } +LL | | } + | |_^ -error: aborting due to 20 previous errors +error: aborting due to 21 previous errors -Some errors have detailed explanations: E0053, E0379, E0706. -For more information about an error, try `rustc --explain E0053`. +Some errors have detailed explanations: E0379, E0391, E0706. +For more information about an error, try `rustc --explain E0379`. diff --git a/src/test/ui/polymorphization/generators.rs b/src/test/ui/polymorphization/generators.rs index f295cf15d08c6..68ea4a026d7bf 100644 --- a/src/test/ui/polymorphization/generators.rs +++ b/src/test/ui/polymorphization/generators.rs @@ -32,7 +32,6 @@ where #[rustc_polymorphize_error] pub fn unused_type() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { - //~^ ERROR item has unused generic parameters || { //~^ ERROR item has unused generic parameters yield 1; @@ -58,7 +57,6 @@ pub fn used_type_in_return() -> impl Generator<(), Yield = u32, Retu #[rustc_polymorphize_error] pub fn unused_const() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { - //~^ ERROR item has unused generic parameters || { //~^ ERROR item has unused generic parameters yield 1; diff --git a/src/test/ui/polymorphization/generators.stderr b/src/test/ui/polymorphization/generators.stderr index c4e566a42d0cf..1152bcb0734a6 100644 --- a/src/test/ui/polymorphization/generators.stderr +++ b/src/test/ui/polymorphization/generators.stderr @@ -8,11 +8,10 @@ LL | #![feature(generic_const_exprs, generators, generator_trait, rustc_attrs)] = note: see issue #76560 for more information error: item has unused generic parameters - --> $DIR/generators.rs:36:5 + --> $DIR/generators.rs:35:5 | LL | pub fn unused_type() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { | - generic parameter `T` is unused -LL | LL | / || { LL | | LL | | yield 1; @@ -21,17 +20,10 @@ LL | | } | |_____^ error: item has unused generic parameters - --> $DIR/generators.rs:34:8 - | -LL | pub fn unused_type() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { - | ^^^^^^^^^^^ - generic parameter `T` is unused - -error: item has unused generic parameters - --> $DIR/generators.rs:62:5 + --> $DIR/generators.rs:60:5 | LL | pub fn unused_const() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { | - generic parameter `T` is unused -LL | LL | / || { LL | | LL | | yield 1; @@ -39,11 +31,5 @@ LL | | 2 LL | | } | |_____^ -error: item has unused generic parameters - --> $DIR/generators.rs:60:8 - | -LL | pub fn unused_const() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { - | ^^^^^^^^^^^^ - generic parameter `T` is unused - -error: aborting due to 4 previous errors; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs index cc36f054bc3a0..49462f52fb4c2 100644 --- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs +++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs @@ -14,7 +14,6 @@ trait B { impl B for A { async fn associated(); //~ ERROR without body //~^ ERROR cannot be declared `async` - //~| ERROR incompatible type for trait } fn main() {} diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr index d3214458eac13..a473f42fc2cf8 100644 --- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr +++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr @@ -44,25 +44,6 @@ LL | async fn associated(); = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait -error[E0053]: method `associated` has an incompatible type for trait - --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:26 - | -LL | async fn associated(); - | ^ - | | - | checked the `Output` of this `async fn`, found opaque type - | expected `()`, found opaque type - | - = note: while checking the return type of the `async fn` -note: type in trait - --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:11:26 - | -LL | async fn associated(); - | ^ - = note: expected fn pointer `fn()` - found fn pointer `fn() -> impl Future` - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0053, E0706. -For more information about an error, try `rustc --explain E0053`. +For more information about this error, try `rustc --explain E0706`. diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 61ac7731777b4..8ddc3f2c34bd8 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -2,14 +2,13 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:37 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | - ^^^^^^^^^^ - | | - | hidden type `Pin<&Foo>` captures the lifetime `'_` as defined here + | ^^^^^^^^^^ | -help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound +note: hidden type `Pin<&' Foo>` captures lifetime smaller than the function body + --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:37 | -LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } - | ++++ +LL | async fn f(self: Pin<&Self>) -> impl Clone { self } + | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index 6f8200739b9de..abdc650c68e78 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -1,8 +1,8 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:31 + --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44 | LL | fn f(self: Pin<&Self>) -> impl Clone { self } - | ----- ^^^^^^^^^^ + | ----- ^^^^ | | | hidden type `Pin<&Foo>` captures the anonymous lifetime defined here | diff --git a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr index d826222a06ae5..07c1d8bccbaba 100644 --- a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr +++ b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr @@ -1,10 +1,11 @@ error[E0277]: the trait bound `(): Bar` is not satisfied - --> $DIR/impl-trait-return-trailing-semicolon.rs:3:13 + --> $DIR/impl-trait-return-trailing-semicolon.rs:3:22 | -LL | fn foo() -> impl Bar { - | ^^^^^^^^ the trait `Bar` is not implemented for `()` -LL | 5; - | - consider removing this semicolon +LL | fn foo() -> impl Bar { + | ______________________^ +LL | | 5; +LL | | } + | |_^ the trait `Bar` is not implemented for `()` error: aborting due to previous error diff --git a/src/test/ui/suggestions/issue-81098.stderr b/src/test/ui/suggestions/issue-81098.stderr index 2a72159e5774b..f13e653cb06bd 100644 --- a/src/test/ui/suggestions/issue-81098.stderr +++ b/src/test/ui/suggestions/issue-81098.stderr @@ -1,19 +1,23 @@ error[E0277]: `()` doesn't implement `std::fmt::Display` - --> $DIR/issue-81098.rs:3:13 + --> $DIR/issue-81098.rs:3:37 | -LL | fn wat() -> impl core::fmt::Display { - | ^^^^^^^^^^^^^^^^^^^^^^^ `()` cannot be formatted with the default formatter +LL | fn wat() -> impl core::fmt::Display { + | _____________________________________^ +LL | | fn why() {} +LL | | } + | |_^ `()` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `()` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead error[E0277]: `()` doesn't implement `std::fmt::Display` - --> $DIR/issue-81098.rs:9:12 + --> $DIR/issue-81098.rs:9:36 | -LL | fn ok() -> impl core::fmt::Display { - | ^^^^^^^^^^^^^^^^^^^^^^^ `()` cannot be formatted with the default formatter -LL | 1; - | - consider removing this semicolon +LL | fn ok() -> impl core::fmt::Display { + | ____________________________________^ +LL | | 1; +LL | | } + | |_^ `()` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `()` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr index a5b50634c71ea..c7f1215c8cc44 100644 --- a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr +++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr @@ -7,13 +7,18 @@ LL | fn iter(&self) -> impl Iterator> { LL | remaining: self.0.iter(), | ------ ^^^^ | | - | ...is used here... + | ...is used and required to live as long as `'static` here | -note: ...and is required to live as long as `'static` here +note: `'static` lifetime requirement introduced by the return type --> $DIR/trait-object-nested-in-impl-trait.rs:27:23 | -LL | fn iter(&self) -> impl Iterator> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn iter(&self) -> impl Iterator> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type +LL | / Iter { +LL | | current: None, +LL | | remaining: self.0.iter(), +LL | | } + | |_________- because of this returned expression help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound | LL | fn iter(&self) -> impl Iterator> + '_ { @@ -32,13 +37,18 @@ LL | fn iter(&self) -> impl Iterator> + '_ { LL | remaining: self.0.iter(), | ------ ^^^^ | | - | ...is used here... + | ...is used and required to live as long as `'static` here | -note: ...and is required to live as long as `'static` here +note: `'static` lifetime requirement introduced by the return type --> $DIR/trait-object-nested-in-impl-trait.rs:38:23 | -LL | fn iter(&self) -> impl Iterator> + '_ { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn iter(&self) -> impl Iterator> + '_ { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type +LL | / Iter { +LL | | current: None, +LL | | remaining: self.0.iter(), +LL | | } + | |_________- because of this returned expression help: to declare that the trait object captures data from argument `self`, you can add an explicit `'_` lifetime bound | LL | fn iter(&self) -> impl Iterator> + '_ { @@ -53,13 +63,18 @@ LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { LL | remaining: self.0.iter(), | ------ ^^^^ | | - | ...is used here... + | ...is used and required to live as long as `'static` here | -note: ...and is required to live as long as `'static` here +note: `'static` lifetime requirement introduced by the return type --> $DIR/trait-object-nested-in-impl-trait.rs:49:30 | -LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type +LL | / Iter { +LL | | current: None, +LL | | remaining: self.0.iter(), +LL | | } + | |_________- because of this returned expression help: to declare that the trait object captures data from argument `self`, you can add an explicit `'a` lifetime bound | LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { @@ -74,13 +89,18 @@ LL | fn iter<'a>(&'a self) -> impl Iterator> { LL | remaining: self.0.iter(), | ------ ^^^^ | | - | ...is used here... + | ...is used and required to live as long as `'static` here | -note: ...and is required to live as long as `'static` here +note: `'static` lifetime requirement introduced by the return type --> $DIR/trait-object-nested-in-impl-trait.rs:60:30 | -LL | fn iter<'a>(&'a self) -> impl Iterator> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn iter<'a>(&'a self) -> impl Iterator> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type +LL | / Iter { +LL | | current: None, +LL | | remaining: self.0.iter(), +LL | | } + | |_________- because of this returned expression help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'a` lifetime bound | LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { diff --git a/src/test/ui/suggestions/match-prev-arm-needing-semi.rs b/src/test/ui/suggestions/match-prev-arm-needing-semi.rs index 6aa93a24d2f04..a02664ad7ca69 100644 --- a/src/test/ui/suggestions/match-prev-arm-needing-semi.rs +++ b/src/test/ui/suggestions/match-prev-arm-needing-semi.rs @@ -16,6 +16,9 @@ fn extra_semicolon() { async fn async_dummy() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type //~| NOTE while checking the return type of the `async fn` //~| NOTE in this expansion of desugaring of `async` block or function +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function +//~| NOTE checked the `Output` of this `async fn`, expected opaque type async fn async_dummy2() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type //~| NOTE checked the `Output` of this `async fn`, found opaque type //~| NOTE while checking the return type of the `async fn` @@ -31,7 +34,7 @@ async fn async_extra_semicolon_same() { } false => async_dummy(), //~ ERROR `match` arms have incompatible types //~^ NOTE expected `()`, found opaque type - //~| NOTE expected type `()` + //~| NOTE expected unit type `()` //~| HELP consider `await`ing on the `Future` }; } @@ -44,7 +47,7 @@ async fn async_extra_semicolon_different() { } false => async_dummy2(), //~ ERROR `match` arms have incompatible types //~^ NOTE expected `()`, found opaque type - //~| NOTE expected type `()` + //~| NOTE expected unit type `()` //~| HELP consider `await`ing on the `Future` }; } @@ -55,7 +58,7 @@ async fn async_different_futures() { //~| HELP consider `await`ing on both `Future`s false => async_dummy2(), //~ ERROR `match` arms have incompatible types //~^ NOTE expected opaque type, found a different opaque type - //~| NOTE expected type `impl Future` + //~| NOTE expected opaque type `impl Future` //~| NOTE distinct uses of `impl Trait` result in different opaque types }; } diff --git a/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr index b55c51b92809a..4c4b782bd6fb1 100644 --- a/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr +++ b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr @@ -1,5 +1,5 @@ error[E0308]: `match` arms have incompatible types - --> $DIR/match-prev-arm-needing-semi.rs:32:18 + --> $DIR/match-prev-arm-needing-semi.rs:35:18 | LL | let _ = match true { | _____________- @@ -20,8 +20,8 @@ note: while checking the return type of the `async fn` | LL | async fn async_dummy() {} | ^ checked the `Output` of this `async fn`, found opaque type - = note: expected type `()` - found opaque type `impl Future` + = note: expected unit type `()` + found opaque type `impl Future` help: consider `await`ing on the `Future` | LL | false => async_dummy().await, @@ -33,7 +33,7 @@ LL + async_dummy() | error[E0308]: `match` arms have incompatible types - --> $DIR/match-prev-arm-needing-semi.rs:45:18 + --> $DIR/match-prev-arm-needing-semi.rs:48:18 | LL | let _ = match true { | _____________- @@ -50,12 +50,12 @@ LL | | }; | |_____- `match` arms have incompatible types | note: while checking the return type of the `async fn` - --> $DIR/match-prev-arm-needing-semi.rs:19:25 + --> $DIR/match-prev-arm-needing-semi.rs:22:25 | LL | async fn async_dummy2() {} | ^ checked the `Output` of this `async fn`, found opaque type - = note: expected type `()` - found opaque type `impl Future` + = note: expected unit type `()` + found opaque type `impl Future` help: consider `await`ing on the `Future` | LL | false => async_dummy2().await, @@ -69,7 +69,7 @@ LL ~ false => Box::new(async_dummy2()), | error[E0308]: `match` arms have incompatible types - --> $DIR/match-prev-arm-needing-semi.rs:56:18 + --> $DIR/match-prev-arm-needing-semi.rs:59:18 | LL | let _ = match true { | _____________- @@ -84,12 +84,17 @@ LL | | }; | |_____- `match` arms have incompatible types | note: while checking the return type of the `async fn` - --> $DIR/match-prev-arm-needing-semi.rs:19:25 + --> $DIR/match-prev-arm-needing-semi.rs:16:24 + | +LL | async fn async_dummy() {} + | ^ checked the `Output` of this `async fn`, expected opaque type +note: while checking the return type of the `async fn` + --> $DIR/match-prev-arm-needing-semi.rs:22:25 | LL | async fn async_dummy2() {} | ^ checked the `Output` of this `async fn`, found opaque type - = note: expected type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:16:24>) - found opaque type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:19:25>) + = note: expected opaque type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:16:24>) + found opaque type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:22:25>) = note: distinct uses of `impl Trait` result in different opaque types help: consider `await`ing on both `Future`s | diff --git a/src/test/ui/suggestions/opaque-type-error.stderr b/src/test/ui/suggestions/opaque-type-error.stderr index e065e0aaa8e06..133ffb0587392 100644 --- a/src/test/ui/suggestions/opaque-type-error.stderr +++ b/src/test/ui/suggestions/opaque-type-error.stderr @@ -1,6 +1,9 @@ error[E0308]: `if` and `else` have incompatible types --> $DIR/opaque-type-error.rs:20:9 | +LL | fn thing_one() -> impl Future> { + | ------------------------------------ the expected opaque type +... LL | fn thing_two() -> impl Future> { | ------------------------------------ the found opaque type ... @@ -13,8 +16,8 @@ LL | | thing_two() LL | | }.await | |_____- `if` and `else` have incompatible types | - = note: expected type `impl Future>` (opaque type at <$DIR/opaque-type-error.rs:8:19>) - found opaque type `impl Future>` (opaque type at <$DIR/opaque-type-error.rs:12:19>) + = note: expected opaque type `impl Future>` (opaque type at <$DIR/opaque-type-error.rs:8:19>) + found opaque type `impl Future>` (opaque type at <$DIR/opaque-type-error.rs:12:19>) = note: distinct uses of `impl Trait` result in different opaque types help: consider `await`ing on both `Future`s | diff --git a/src/test/ui/type-alias-impl-trait/argument-types.rs b/src/test/ui/type-alias-impl-trait/argument-types.rs index 8427b5b1fe854..185207b9800bb 100644 --- a/src/test/ui/type-alias-impl-trait/argument-types.rs +++ b/src/test/ui/type-alias-impl-trait/argument-types.rs @@ -1,14 +1,12 @@ #![feature(type_alias_impl_trait)] #![allow(dead_code)] - +// check-pass use std::fmt::Debug; type Foo = impl Debug; -// FIXME: This should compile, but it currently doesn't fn foo1(mut x: Foo) { x = 22_u32; - //~^ ERROR: mismatched types [E0308] } fn foo2(mut x: Foo) { diff --git a/src/test/ui/type-alias-impl-trait/argument-types.stderr b/src/test/ui/type-alias-impl-trait/argument-types.stderr deleted file mode 100644 index a87e44a048b25..0000000000000 --- a/src/test/ui/type-alias-impl-trait/argument-types.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/argument-types.rs:10:9 - | -LL | type Foo = impl Debug; - | ---------- the expected opaque type -... -LL | fn foo1(mut x: Foo) { - | --- expected due to this parameter type -LL | x = 22_u32; - | ^^^^^^ expected opaque type, found `u32` - | - = note: expected opaque type `impl Debug` - found type `u32` - -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/auto-trait-leakage3.rs b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs index 5fb7a9473d3df..b456b1445e784 100644 --- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs +++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs @@ -6,6 +6,7 @@ mod m { type Foo = impl std::fmt::Debug; //~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391] + //~| ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391] pub fn foo() -> Foo { 22_u32 diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr index c0147e56c9364..4c44875b4a548 100644 --- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr +++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr @@ -5,11 +5,10 @@ LL | type Foo = impl std::fmt::Debug; | ^^^^^^^^^^^^^^^^^^^^ | note: ...which requires type-checking `m::bar`... - --> $DIR/auto-trait-leakage3.rs:15:9 + --> $DIR/auto-trait-leakage3.rs:15:5 | -LL | is_send(foo()); - | ^^^^^^^ - = note: ...which requires evaluating trait selection obligation `impl core::fmt::Debug: core::marker::Send`... +LL | pub fn bar() { + | ^^^^^^^^^^^^ = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle note: cycle used when checking item types in module `m` --> $DIR/auto-trait-leakage3.rs:6:1 @@ -17,6 +16,24 @@ note: cycle used when checking item types in module `m` LL | mod m { | ^^^^^ -error: aborting due to previous error +error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}` + --> $DIR/auto-trait-leakage3.rs:7:16 + | +LL | type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires type-checking `m::bar`... + --> $DIR/auto-trait-leakage3.rs:15:5 + | +LL | pub fn bar() { + | ^^^^^^^^^^^^ + = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in module `m` + --> $DIR/auto-trait-leakage3.rs:6:1 + | +LL | mod m { + | ^^^^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs index cee8186dd8f8c..2177bf3b1c498 100644 --- a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs +++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs @@ -14,6 +14,6 @@ trait Trait {} impl Trait for () {} fn foo_desugared(_: T) -> Foo { - //~^ ERROR non-defining opaque type use in defining scope () + //~^ ERROR type annotations needed } diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr index 03e696fe89803..4ff14333c1969 100644 --- a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr +++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr @@ -1,14 +1,8 @@ -error: non-defining opaque type use in defining scope - --> $DIR/bound_reduction2.rs:16:46 +error[E0282]: type annotations needed + --> $DIR/bound_reduction2.rs:17:5 | -LL | fn foo_desugared(_: T) -> Foo { - | ^^^^^^^^^^^^^ - | -note: used non-generic type `::Assoc` for generic parameter - --> $DIR/bound_reduction2.rs:9:10 - | -LL | type Foo = impl Trait; - | ^ +LL | () + | ^^ cannot infer type error: could not find defining uses --> $DIR/bound_reduction2.rs:9:15 @@ -18,3 +12,4 @@ LL | type Foo = impl Trait; error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs b/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs index eecef2338c146..d694d3822388e 100644 --- a/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs @@ -4,11 +4,12 @@ #![feature(type_alias_impl_trait)] type X<'a> = impl Into<&'static str> + From<&'a str>; -//~^ ERROR mismatched types +//~^ ERROR could not find defining uses fn f<'a: 'static>(t: &'a str) -> X<'a> { //~^ WARNING unnecessary lifetime parameter t + //~^ ERROR non-defining opaque type use } fn extend_lt<'a>(o: &'a str) -> &'static str { diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr index da9f81d6bd370..11bc926c961a5 100644 --- a/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr @@ -6,21 +6,20 @@ LL | fn f<'a: 'static>(t: &'a str) -> X<'a> { | = help: you can use the `'static` lifetime directly, in place of `'a` -error[E0308]: mismatched types - --> $DIR/bounds-are-checked.rs:6:14 +error: non-defining opaque type use in defining scope + --> $DIR/bounds-are-checked.rs:11:5 | LL | type X<'a> = impl Into<&'static str> + From<&'a str>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch - | - = note: expected trait `From<&'a str>` - found trait `From<&'static str>` -note: the lifetime `'a` as defined here... - --> $DIR/bounds-are-checked.rs:6:8 + | -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type +... +LL | t + | ^ + +error: could not find defining uses + --> $DIR/bounds-are-checked.rs:6:14 | LL | type X<'a> = impl Into<&'static str> + From<&'a str>; - | ^^ - = note: ...does not necessarily outlive the static lifetime + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr index 0b4c262bbb43b..4564ef6b8f6a0 100644 --- a/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr +++ b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr @@ -10,13 +10,11 @@ error[E0308]: mismatched types LL | pub type Boo = impl ::std::fmt::Debug; | ---------------------- the expected opaque type ... -LL | fn bomp() -> boo::Boo { - | -------- expected `impl Debug` because of return type LL | "" | ^^ expected opaque type, found `&str` | = note: expected opaque type `impl Debug` - found reference `&'static str` + found reference `&str` error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs b/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs index 95cbcfec2dc15..7740f774ebca4 100644 --- a/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs +++ b/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs @@ -1,5 +1,5 @@ #![feature(type_alias_impl_trait)] - +// check-pass fn main() {} // two definitions with different types @@ -10,11 +10,9 @@ fn foo() -> Foo { } fn bar() -> Foo { - //~^ ERROR concrete type differs from previous panic!() } fn boo() -> Foo { - //~^ ERROR concrete type differs from previous loop {} } diff --git a/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr b/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr deleted file mode 100644 index 6274029e4f524..0000000000000 --- a/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error: concrete type differs from previous defining opaque type use - --> $DIR/different_defining_uses_never_type.rs:12:1 - | -LL | fn bar() -> Foo { - | ^^^^^^^^^^^^^^^ expected `&'static str`, got `()` - | -note: previous use here - --> $DIR/different_defining_uses_never_type.rs:8:1 - | -LL | fn foo() -> Foo { - | ^^^^^^^^^^^^^^^ - -error: concrete type differs from previous defining opaque type use - --> $DIR/different_defining_uses_never_type.rs:17:1 - | -LL | fn boo() -> Foo { - | ^^^^^^^^^^^^^^^ expected `&'static str`, got `()` - | -note: previous use here - --> $DIR/different_defining_uses_never_type.rs:8:1 - | -LL | fn foo() -> Foo { - | ^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/type-alias-impl-trait/field-types.rs b/src/test/ui/type-alias-impl-trait/field-types.rs index 91494a82d0fb2..d99ed58127bd4 100644 --- a/src/test/ui/type-alias-impl-trait/field-types.rs +++ b/src/test/ui/type-alias-impl-trait/field-types.rs @@ -1,12 +1,11 @@ #![feature(type_alias_impl_trait)] #![allow(dead_code)] -// FIXME This should compile, but it currently doesn't +// check-pass use std::fmt::Debug; type Foo = impl Debug; -//~^ ERROR: could not find defining uses struct Bar { foo: Foo, @@ -14,7 +13,6 @@ struct Bar { fn bar() -> Bar { Bar { foo: "foo" } - //~^ ERROR: mismatched types [E0308] } fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/field-types.stderr b/src/test/ui/type-alias-impl-trait/field-types.stderr deleted file mode 100644 index 18c2abbdf3721..0000000000000 --- a/src/test/ui/type-alias-impl-trait/field-types.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/field-types.rs:16:16 - | -LL | type Foo = impl Debug; - | ---------- the expected opaque type -... -LL | Bar { foo: "foo" } - | ^^^^^ expected opaque type, found `&str` - | - = note: expected opaque type `impl Debug` - found reference `&'static str` - -error: could not find defining uses - --> $DIR/field-types.rs:8:12 - | -LL | type Foo = impl Debug; - | ^^^^^^^^^^ - -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/generic_duplicate_lifetime_param.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs index 885aae619d6a2..e7768c246c207 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs @@ -6,6 +6,6 @@ type Two<'a, 'b> = impl std::fmt::Debug; //~^ ERROR could not find defining uses fn one<'a>(t: &'a ()) -> Two<'a, 'a> { - //~^ ERROR non-defining opaque type use t + //~^ ERROR non-defining opaque type use } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr index b99c6a51f4b1d..bcd3a71dc18fb 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr @@ -1,8 +1,8 @@ error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_lifetime_param.rs:8:26 + --> $DIR/generic_duplicate_lifetime_param.rs:9:5 | -LL | fn one<'a>(t: &'a ()) -> Two<'a, 'a> { - | ^^^^^^^^^^^ +LL | t + | ^ | note: lifetime used multiple times --> $DIR/generic_duplicate_lifetime_param.rs:5:10 diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs index 33cd2f6ba0753..e854434a59fc9 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs @@ -13,16 +13,16 @@ type TwoConsts = impl Debug; //~^ ERROR could not find defining uses fn one_ty(t: T) -> TwoTys { - //~^ ERROR non-defining opaque type use in defining scope t + //~^ ERROR non-defining opaque type use in defining scope } fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> { - //~^ ERROR non-defining opaque type use in defining scope t + //~^ ERROR non-defining opaque type use in defining scope } fn one_const(t: *mut [u8; N]) -> TwoConsts { - //~^ ERROR non-defining opaque type use in defining scope t + //~^ ERROR non-defining opaque type use in defining scope } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr index 52c60d1777e49..48b3a4d287a7a 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr @@ -1,8 +1,8 @@ error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use.rs:15:30 + --> $DIR/generic_duplicate_param_use.rs:16:5 | -LL | fn one_ty(t: T) -> TwoTys { - | ^^^^^^^^^^^^ +LL | t + | ^ | note: type used multiple times --> $DIR/generic_duplicate_param_use.rs:8:13 @@ -17,10 +17,10 @@ LL | type TwoTys = impl Debug; | ^^^^^^^^^^ error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use.rs:20:36 + --> $DIR/generic_duplicate_param_use.rs:21:5 | -LL | fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> { - | ^^^^^^^^^^^^^^^^^^^^ +LL | t + | ^ | note: lifetime used multiple times --> $DIR/generic_duplicate_param_use.rs:10:19 @@ -35,10 +35,10 @@ LL | type TwoLifetimes<'a, 'b> = impl Debug; | ^^^^^^^^^^ error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use.rs:25:50 + --> $DIR/generic_duplicate_param_use.rs:26:5 | -LL | fn one_const(t: *mut [u8; N]) -> TwoConsts { - | ^^^^^^^^^^^^^^^ +LL | t + | ^ | note: constant used multiple times --> $DIR/generic_duplicate_param_use.rs:12:22 diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs index 04fb57b39c052..da9dd5baa3d0f 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs @@ -9,8 +9,8 @@ type Two = impl Debug; //~^ ERROR `T` doesn't implement `Debug` fn one(t: T) -> Two { - //~^ ERROR non-defining opaque type use in defining scope t + //~^ ERROR non-defining opaque type use in defining scope } fn two(t: T, _: U) -> Two { diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr index fca9b70d18441..e62218fe0832c 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr @@ -1,8 +1,8 @@ error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use2.rs:11:27 + --> $DIR/generic_duplicate_param_use2.rs:12:5 | -LL | fn one(t: T) -> Two { - | ^^^^^^^^^ +LL | t + | ^ | note: type used multiple times --> $DIR/generic_duplicate_param_use2.rs:8:10 diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs index 1a755d3902612..b21280e2db56a 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs @@ -9,8 +9,8 @@ type Two = impl Debug; //~^ ERROR `T` doesn't implement `Debug` fn one(t: T) -> Two { - //~^ ERROR non-defining opaque type use in defining scope t + //~^ ERROR non-defining opaque type use in defining scope } fn two(t: T, _: U) -> Two { diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr index 90b04c043a00c..cb4e0f04aa146 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr @@ -1,8 +1,8 @@ error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use3.rs:11:27 + --> $DIR/generic_duplicate_param_use3.rs:12:5 | -LL | fn one(t: T) -> Two { - | ^^^^^^^^^ +LL | t + | ^ | note: type used multiple times --> $DIR/generic_duplicate_param_use3.rs:8:10 diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs index 50d95c83d58e6..1e22930a5034b 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs @@ -9,8 +9,8 @@ type Two = impl Debug; //~^ ERROR `U` doesn't implement `Debug` fn one(t: T) -> Two { - //~^ ERROR non-defining opaque type use in defining scope t + //~^ ERROR non-defining opaque type use in defining scope } fn three(_: T, u: U) -> Two { diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr index c4be2fa83f130..64268abce50c0 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr @@ -1,8 +1,8 @@ error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use4.rs:11:27 + --> $DIR/generic_duplicate_param_use4.rs:12:5 | -LL | fn one(t: T) -> Two { - | ^^^^^^^^^ +LL | t + | ^ | note: type used multiple times --> $DIR/generic_duplicate_param_use4.rs:8:10 diff --git a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs index cf43085877f4c..2fe5c68ab576f 100644 --- a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs +++ b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs @@ -14,16 +14,16 @@ type OneConst = impl Debug; // Not defining uses, because they doesn't define *all* possible generics. fn concrete_ty() -> OneTy { - //~^ ERROR non-defining opaque type use in defining scope 5u32 + //~^ ERROR non-defining opaque type use in defining scope } fn concrete_lifetime() -> OneLifetime<'static> { - //~^ ERROR non-defining opaque type use in defining scope 6u32 + //~^ ERROR non-defining opaque type use in defining scope } fn concrete_const() -> OneConst<{ 123 }> { - //~^ ERROR non-defining opaque type use in defining scope 7u32 + //~^ ERROR non-defining opaque type use in defining scope } diff --git a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr index 3aa42a25484d1..1b2084b630f29 100644 --- a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr @@ -1,8 +1,8 @@ error: non-defining opaque type use in defining scope - --> $DIR/generic_nondefining_use.rs:16:21 + --> $DIR/generic_nondefining_use.rs:17:5 | -LL | fn concrete_ty() -> OneTy { - | ^^^^^^^^^^ +LL | 5u32 + | ^^^^ | note: used non-generic type `u32` for generic parameter --> $DIR/generic_nondefining_use.rs:7:12 @@ -17,13 +17,13 @@ LL | type OneTy = impl Debug; | ^^^^^^^^^^ error: non-defining opaque type use in defining scope - --> $DIR/generic_nondefining_use.rs:21:27 + --> $DIR/generic_nondefining_use.rs:22:5 | LL | type OneLifetime<'a> = impl Debug; | -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type ... -LL | fn concrete_lifetime() -> OneLifetime<'static> { - | ^^^^^^^^^^^^^^^^^^^^ +LL | 6u32 + | ^^^^ error: could not find defining uses --> $DIR/generic_nondefining_use.rs:9:24 @@ -32,10 +32,10 @@ LL | type OneLifetime<'a> = impl Debug; | ^^^^^^^^^^ error: non-defining opaque type use in defining scope - --> $DIR/generic_nondefining_use.rs:26:24 + --> $DIR/generic_nondefining_use.rs:27:5 | -LL | fn concrete_const() -> OneConst<{ 123 }> { - | ^^^^^^^^^^^^^^^^^ +LL | 7u32 + | ^^^^ | note: used non-generic constant `123_usize` for generic parameter --> $DIR/generic_nondefining_use.rs:11:21 diff --git a/src/test/ui/type-alias-impl-trait/generic_not_used.rs b/src/test/ui/type-alias-impl-trait/generic_not_used.rs index dd6300a64f42e..c70f473cff578 100644 --- a/src/test/ui/type-alias-impl-trait/generic_not_used.rs +++ b/src/test/ui/type-alias-impl-trait/generic_not_used.rs @@ -6,6 +6,6 @@ type WrongGeneric = impl 'static; //~^ ERROR: at least one trait must be specified fn wrong_generic(_: U, v: V) -> WrongGeneric { - //~^ ERROR type parameter `V` is part of concrete type but not used in parameter list v + //~^ ERROR type parameter `V` is part of concrete type but not used in parameter list } diff --git a/src/test/ui/type-alias-impl-trait/generic_not_used.stderr b/src/test/ui/type-alias-impl-trait/generic_not_used.stderr index 8015ff7eded90..fd720239a5239 100644 --- a/src/test/ui/type-alias-impl-trait/generic_not_used.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_not_used.stderr @@ -5,14 +5,10 @@ LL | type WrongGeneric = impl 'static; | ^^^^^^^^^^^^ error: type parameter `V` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/generic_not_used.rs:8:73 + --> $DIR/generic_not_used.rs:9:5 | -LL | fn wrong_generic(_: U, v: V) -> WrongGeneric { - | _________________________________________________________________________^ -LL | | -LL | | v -LL | | } - | |_^ +LL | v + | ^ error: aborting due to 2 previous errors 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 f4e1de8e50f68..8c5659ed12c08 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 @@ -1,33 +1,31 @@ error: at least one trait must be specified - --> $DIR/generic_type_does_not_live_long_enough.rs:9:24 + --> $DIR/generic_type_does_not_live_long_enough.rs:10:24 | LL | type WrongGeneric = impl 'static; | ^^^^^^^^^^^^ -error[E0308]: mismatched types +error: non-defining opaque type use in defining scope --> $DIR/generic_type_does_not_live_long_enough.rs:6:18 | LL | let z: i32 = x; - | --- ^ expected `i32`, found opaque type - | | - | expected due to this -... -LL | type WrongGeneric = impl 'static; - | ------------ the found opaque type + | ^ + | +note: used non-generic type `&'static i32` for generic parameter + --> $DIR/generic_type_does_not_live_long_enough.rs:10:19 | - = note: expected type `i32` - found opaque type `impl Sized` +LL | type WrongGeneric = impl 'static; + | ^ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/generic_type_does_not_live_long_enough.rs:12:30 + --> $DIR/generic_type_does_not_live_long_enough.rs:15:5 | -LL | fn wrong_generic(t: T) -> WrongGeneric { - | ^^^^^^^^^^^^^^^ +LL | t + | ^ | = help: consider adding an explicit lifetime bound `T: 'static`... 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:10:24 | LL | type WrongGeneric = impl 'static; | ^^^^^^^^^^^^ @@ -37,5 +35,4 @@ LL | type WrongGeneric = impl 'static; error: aborting due to 4 previous errors -Some errors have detailed explanations: E0308, E0310. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0310`. 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 78d25e30e0382..4a7d640fe84de 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 @@ -3,13 +3,15 @@ fn main() { let y = 42; let x = wrong_generic(&y); - let z: i32 = x; //~ ERROR mismatched types + let z: i32 = x; + //~^ ERROR non-defining opaque type use } type WrongGeneric = impl 'static; //~^ ERROR: at least one trait must be specified +//~| ERROR could not find defining uses fn wrong_generic(t: T) -> WrongGeneric { - //~^ ERROR the parameter type `T` may not live long enough t + //~^ ERROR the parameter type `T` may not live long enough } 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 568784372e519..22f8a757aad1d 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 @@ -1,32 +1,35 @@ error: at least one trait must be specified - --> $DIR/generic_type_does_not_live_long_enough.rs:9:24 + --> $DIR/generic_type_does_not_live_long_enough.rs:10:24 | LL | type WrongGeneric = impl 'static; | ^^^^^^^^^^^^ -error[E0308]: mismatched types +error: non-defining opaque type use in defining scope --> $DIR/generic_type_does_not_live_long_enough.rs:6:18 | LL | let z: i32 = x; - | --- ^ expected `i32`, found opaque type - | | - | expected due to this -... -LL | type WrongGeneric = impl 'static; - | ------------ the found opaque type + | ^ + | +note: used non-generic type `&'static i32` for generic parameter + --> $DIR/generic_type_does_not_live_long_enough.rs:10:19 | - = note: expected type `i32` - found opaque type `impl Sized` +LL | type WrongGeneric = impl 'static; + | ^ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/generic_type_does_not_live_long_enough.rs:12:30 + --> $DIR/generic_type_does_not_live_long_enough.rs:15:5 | LL | fn wrong_generic(t: T) -> WrongGeneric { - | - ^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds - | | - | help: consider adding an explicit lifetime bound...: `T: 'static` + | - help: consider adding an explicit lifetime bound...: `T: 'static` +LL | t + | ^ ...so that the type `T` will meet its required lifetime bounds + +error: could not find defining uses + --> $DIR/generic_type_does_not_live_long_enough.rs:10:24 + | +LL | type WrongGeneric = impl 'static; + | ^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0308, E0310. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/type-alias-impl-trait/inference-cycle.rs b/src/test/ui/type-alias-impl-trait/inference-cycle.rs index c781e200bf8ee..d00b6ce3f82c5 100644 --- a/src/test/ui/type-alias-impl-trait/inference-cycle.rs +++ b/src/test/ui/type-alias-impl-trait/inference-cycle.rs @@ -3,7 +3,8 @@ mod m { type Foo = impl std::fmt::Debug; - //~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391] + //~^ ERROR cycle detected + //~| ERROR cycle detected // Cycle: error today, but it'd be nice if it eventually worked @@ -15,9 +16,8 @@ mod m { is_send(foo()); // Today: error } - fn baz() { + fn baz() { //~ ERROR concrete type differs from previous defining opaque type use let f: Foo = 22_u32; - //~^ ERROR: mismatched types [E0308] } fn is_send(_: T) {} diff --git a/src/test/ui/type-alias-impl-trait/inference-cycle.stderr b/src/test/ui/type-alias-impl-trait/inference-cycle.stderr index e12124664778e..90032f589e009 100644 --- a/src/test/ui/type-alias-impl-trait/inference-cycle.stderr +++ b/src/test/ui/type-alias-impl-trait/inference-cycle.stderr @@ -5,11 +5,10 @@ LL | type Foo = impl std::fmt::Debug; | ^^^^^^^^^^^^^^^^^^^^ | note: ...which requires type-checking `m::bar`... - --> $DIR/inference-cycle.rs:15:9 + --> $DIR/inference-cycle.rs:15:5 | -LL | is_send(foo()); // Today: error - | ^^^^^^^ - = note: ...which requires evaluating trait selection obligation `impl core::fmt::Debug: core::marker::Send`... +LL | pub fn bar() { + | ^^^^^^^^^^^^ = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle note: cycle used when checking item types in module `m` --> $DIR/inference-cycle.rs:4:1 @@ -17,21 +16,36 @@ note: cycle used when checking item types in module `m` LL | mod m { | ^^^^^ -error[E0308]: mismatched types - --> $DIR/inference-cycle.rs:19:22 +error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}` + --> $DIR/inference-cycle.rs:5:16 | LL | type Foo = impl std::fmt::Debug; - | -------------------- the expected opaque type -... -LL | let f: Foo = 22_u32; - | --- ^^^^^^ expected opaque type, found `u32` - | | - | expected due to this - | - = note: expected opaque type `impl Debug` - found type `u32` + | ^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires type-checking `m::bar`... + --> $DIR/inference-cycle.rs:15:5 + | +LL | pub fn bar() { + | ^^^^^^^^^^^^ + = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in module `m` + --> $DIR/inference-cycle.rs:4:1 + | +LL | mod m { + | ^^^^^ + +error: concrete type differs from previous defining opaque type use + --> $DIR/inference-cycle.rs:19:5 + | +LL | fn baz() { + | ^^^^^^^^ expected `()`, got `u32` + | +note: previous use here + --> $DIR/inference-cycle.rs:11:5 + | +LL | pub fn foo() -> Foo { + | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0308, E0391. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/type-alias-impl-trait/issue-53598.rs b/src/test/ui/type-alias-impl-trait/issue-53598.rs index 37b330ba4b8fc..34be420274409 100644 --- a/src/test/ui/type-alias-impl-trait/issue-53598.rs +++ b/src/test/ui/type-alias-impl-trait/issue-53598.rs @@ -18,8 +18,8 @@ impl Foo for S2 { type Item = impl Debug; fn foo(_: T) -> Self::Item { - //~^ Error type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias S::(Default::default()) + //~^ Error type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias } } diff --git a/src/test/ui/type-alias-impl-trait/issue-53598.stderr b/src/test/ui/type-alias-impl-trait/issue-53598.stderr index 4c8144a235930..34f0aa0d98d9a 100644 --- a/src/test/ui/type-alias-impl-trait/issue-53598.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-53598.stderr @@ -1,12 +1,8 @@ error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-53598.rs:20:42 + --> $DIR/issue-53598.rs:21:9 | -LL | fn foo(_: T) -> Self::Item { - | __________________________________________^ -LL | | -LL | | S::(Default::default()) -LL | | } - | |_____^ +LL | S::(Default::default()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error 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 625e46b6bc012..91aa77f2268b2 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,10 +15,11 @@ struct X; impl Foo for X { type Bar = impl Baz; + //~^ ERROR could not find defining uses fn bar(&self) -> Self::Bar { - //~^ ERROR implementation of `FnOnce` is not general enough |x| x + //~^ ERROR implementation of `FnOnce` is not general enough } } 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 54d237159d80b..c684a8bf6b01f 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,11 +1,17 @@ error: implementation of `FnOnce` is not general enough - --> $DIR/issue-57611-trait-alias.rs:19:22 + --> $DIR/issue-57611-trait-alias.rs:21:9 | -LL | fn bar(&self) -> Self::Bar { - | ^^^^^^^^^ implementation of `FnOnce` is not general enough +LL | |x| x + | ^^^^^ 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` -error: aborting due to previous error +error: could not find defining uses + --> $DIR/issue-57611-trait-alias.rs:17:16 + | +LL | type Bar = impl Baz; + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/issue-57700.rs b/src/test/ui/type-alias-impl-trait/issue-57700.rs index f1db4d3291b40..ba8bda76cecf6 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57700.rs +++ b/src/test/ui/type-alias-impl-trait/issue-57700.rs @@ -14,8 +14,8 @@ impl Foo for C { type Bar = impl Foo; fn foo(self: impl Deref) -> Self::Bar { - //~^ Error type parameter `impl Deref` is part of concrete type but not used in parameter list for the `impl Trait` type alias self + //~^ Error type parameter `impl Deref` is part of concrete type but not used in parameter list for the `impl Trait` type alias } } diff --git a/src/test/ui/type-alias-impl-trait/issue-57700.stderr b/src/test/ui/type-alias-impl-trait/issue-57700.stderr index c701e3e74ef59..56ad997f84314 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57700.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57700.stderr @@ -1,12 +1,8 @@ error: type parameter `impl Deref` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-57700.rs:16:58 + --> $DIR/issue-57700.rs:17:9 | -LL | fn foo(self: impl Deref) -> Self::Bar { - | __________________________________________________________^ -LL | | -LL | | self -LL | | } - | |_____^ +LL | self + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/issue-58951-2.rs b/src/test/ui/type-alias-impl-trait/issue-58951-2.rs new file mode 100644 index 0000000000000..e4ba7f8e2a623 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-58951-2.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +mod defining_use_scope { + pub type A = impl Iterator; + + pub fn def_a() -> A { + 0..1 + } +} +use defining_use_scope::*; + +pub fn use_a() { + def_a().map(|x| x); +} + +fn main() {} 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 9d2ba849c8667..f2ecd5a455bfd 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,10 @@ trait Bug { impl Bug for &() { type Item = impl Bug; //~ ERROR `impl Trait` in type aliases is unstable + //~^ ERROR could not find defining uses const FUN: fn() -> Self::Item = || (); //~^ ERROR the trait bound `(): Bug` is not satisfied - //~| ERROR non-defining opaque type use in defining scope } 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 62ab7eb456010..fbe071ac85773 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60371.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60371.stderr @@ -8,22 +8,19 @@ LL | type Item = impl Bug; = 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:12:40 + --> $DIR/issue-60371.rs:13:40 | LL | const FUN: fn() -> Self::Item = || (); - | ^ the trait `Bug` is not implemented for `()` + | ^^ the trait `Bug` is not implemented for `()` | = help: the following implementations were found: <&() as Bug> -error: non-defining opaque type use in defining scope - --> $DIR/issue-60371.rs:12:37 +error: could not find defining uses + --> $DIR/issue-60371.rs:10:17 | -LL | impl Bug for &() { - | - cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type -... -LL | const FUN: fn() -> Self::Item = || (); - | ^^^^^ +LL | type Item = impl Bug; + | ^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.rs b/src/test/ui/type-alias-impl-trait/issue-60564.rs index 44dcec2c3da98..e645663c3420a 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60564.rs +++ b/src/test/ui/type-alias-impl-trait/issue-60564.rs @@ -18,8 +18,8 @@ where { type BitsIter = IterBitsIter; fn iter_bits(self, n: u8) -> Self::BitsIter { - //~^ ERROR non-defining opaque type use in defining scope (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) + //~^ ERROR non-defining opaque type use in defining scope } } diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.stderr b/src/test/ui/type-alias-impl-trait/issue-60564.stderr index 6b73fbef011ec..0a260a247c082 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60564.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60564.stderr @@ -1,8 +1,8 @@ error: non-defining opaque type use in defining scope - --> $DIR/issue-60564.rs:20:34 + --> $DIR/issue-60564.rs:21:9 | -LL | fn iter_bits(self, n: u8) -> Self::BitsIter { - | ^^^^^^^^^^^^^^ +LL | (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: used non-generic type `u8` for generic parameter --> $DIR/issue-60564.rs:8:25 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 875cce4df2390..3d20b7e37190d 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63279.rs +++ b/src/test/ui/type-alias-impl-trait/issue-63279.rs @@ -3,9 +3,12 @@ #![feature(type_alias_impl_trait)] type Closure = impl FnOnce(); +//~^ ERROR could not find defining uses fn c() -> Closure { - || -> Closure { || () } //~ ERROR: mismatched types + || -> Closure { || () } + //~^ ERROR: mismatched types + //~| ERROR: expected a `FnOnce<()>` closure, found `()` } 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 5fde8c2ef1e11..385e816eebf52 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63279.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-63279.stderr @@ -1,17 +1,32 @@ +error[E0277]: expected a `FnOnce<()>` closure, found `()` + --> $DIR/issue-63279.rs:9:11 + | +LL | || -> Closure { || () } + | ^^^^^^^ expected an `FnOnce<()>` closure, found `()` + | + = help: the trait `FnOnce<()>` is not implemented for `()` + = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` + error[E0308]: mismatched types - --> $DIR/issue-63279.rs:8:5 + --> $DIR/issue-63279.rs:9:21 | -LL | type Closure = impl FnOnce(); - | ------------- the found opaque type -... LL | || -> Closure { || () } - | ^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure + | ^^^^^ expected `()`, found closure | - = 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 + = note: expected unit type `()` + found closure `[closure@$DIR/issue-63279.rs:9:21: 9:26]` +help: you might have meant to return this value + | +LL | || -> Closure { return || (); } + | ++++++ + + +error: could not find defining uses + --> $DIR/issue-63279.rs:5:16 + | +LL | type Closure = impl FnOnce(); + | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/issue-63355.rs b/src/test/ui/type-alias-impl-trait/issue-63355.rs index ff4fd5dcec73c..7066a0535e184 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63355.rs +++ b/src/test/ui/type-alias-impl-trait/issue-63355.rs @@ -1,6 +1,5 @@ #![feature(type_alias_impl_trait)] -#![feature(type_alias_impl_trait)] -#![allow(incomplete_features)] +// check-pass pub trait Foo {} @@ -28,11 +27,8 @@ impl Bar for () { } } -// FIXME(#86731): The below is illegal use of `type_alias_impl_trait` -// but the compiler doesn't report it, we should fix it. pub type FooImpl = impl Foo; pub type BarImpl = impl Bar; -//~^ ERROR: type mismatch resolving `<() as Bar>::Foo == ()` impl Baz for () { type Foo = FooImpl; diff --git a/src/test/ui/type-alias-impl-trait/issue-63355.stderr b/src/test/ui/type-alias-impl-trait/issue-63355.stderr deleted file mode 100644 index 6fc6b4bfe1f00..0000000000000 --- a/src/test/ui/type-alias-impl-trait/issue-63355.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0271]: type mismatch resolving `<() as Bar>::Foo == ()` - --> $DIR/issue-63355.rs:34:20 - | -LL | pub type FooImpl = impl Foo; - | -------- the found opaque type -LL | pub type BarImpl = impl Bar; - | ^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Bar>::Foo == ()` - | -note: expected this to be `()` - --> $DIR/issue-63355.rs:24:16 - | -LL | type Foo = FooImpl; - | ^^^^^^^ - = note: expected unit type `()` - found opaque type `impl Foo` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr index 721f99a3f0d18..3524d1ea8a4d5 100644 --- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr @@ -1,8 +1,8 @@ error: non-defining opaque type use in defining scope - --> $DIR/issue-68368-non-defining-use-2.rs:9:15 + --> $DIR/issue-68368-non-defining-use-2.rs:9:29 | LL | fn f<'a>() -> Alias<'a, ()> {} - | ^^^^^^^^^^^^^ + | ^^ | note: used non-generic type `()` for generic parameter --> $DIR/issue-68368-non-defining-use-2.rs:7:16 diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr index f5b8fccf65d16..3f7c57f721d55 100644 --- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr @@ -1,8 +1,8 @@ error: non-defining opaque type use in defining scope - --> $DIR/issue-68368-non-defining-use.rs:9:15 + --> $DIR/issue-68368-non-defining-use.rs:9:29 | LL | fn f<'a>() -> Alias<'a, ()> {} - | ^^^^^^^^^^^^^ + | ^^ | note: used non-generic type `()` for generic parameter --> $DIR/issue-68368-non-defining-use.rs:7:16 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 ad641eaa00d38..eceaef30e0429 100644 --- a/src/test/ui/type-alias-impl-trait/issue-74280.rs +++ b/src/test/ui/type-alias-impl-trait/issue-74280.rs @@ -3,6 +3,7 @@ #![feature(type_alias_impl_trait)] type Test = impl Copy; +//~^ ERROR could not find defining uses fn test() -> Test { let y = || -> Test { () }; 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 f6b369dd8d518..475a005223426 100644 --- a/src/test/ui/type-alias-impl-trait/issue-74280.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-74280.stderr @@ -1,9 +1,17 @@ error[E0308]: mismatched types - --> $DIR/issue-74280.rs:9:5 + --> $DIR/issue-74280.rs:10:5 | +LL | let y = || -> Test { () }; + | -- type expected due to this LL | 7 | ^ expected `()`, found integer -error: aborting due to previous error +error: could not find defining uses + --> $DIR/issue-74280.rs:5:13 + | +LL | type Test = impl Copy; + | ^^^^^^^^^ + +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-77179.stderr b/src/test/ui/type-alias-impl-trait/issue-77179.stderr index 15205ba9b419e..9e742a2550029 100644 --- a/src/test/ui/type-alias-impl-trait/issue-77179.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-77179.stderr @@ -5,7 +5,7 @@ LL | fn test() -> Pointer<_> { | --------^- | | | | | not allowed in type signatures - | help: replace with the correct return type: `Box` + | help: replace with the correct return type: `impl Deref` error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/issue-89686.stderr b/src/test/ui/type-alias-impl-trait/issue-89686.stderr index 19ed9a7476c1b..3a75dc6fe7ba0 100644 --- a/src/test/ui/type-alias-impl-trait/issue-89686.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-89686.stderr @@ -2,18 +2,18 @@ error[E0271]: type mismatch resolving ` as --> $DIR/issue-89686.rs:7:17 | LL | type G<'a, T> = impl Future; - | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()` ... LL | async move { self.f().await } - | ------------------ the found `async` block + | ------------------ the expected `async` block | ::: $SRC_DIR/core/src/future/mod.rs:LL:COL | LL | pub const fn from_generator(gen: T) -> impl Future - | ------------------------------- the found opaque type + | ------------------------------- the expected opaque type | - = note: expected unit type `()` - found associated type ` as Future>::Output` + = note: expected associated type ` as Future>::Output` + found unit type `()` = help: consider constraining the associated type ` as Future>::Output` to `()` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html 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 da845e86147b7..49ce39c57d193 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,10 +5,11 @@ #![feature(type_alias_impl_trait)] type X = impl Into<&'static A>; +//~^ ERROR could not find defining uses fn f(a: &'static A, b: B) -> (X, X) { - //~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied (a, a) + //~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied } fn main() { 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 4df2f52a9e427..4c3f527a21421 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:9:45 + --> $DIR/multiple-def-uses-in-one-fn.rs:11:9 | -LL | fn f(a: &'static A, b: B) -> (X, X) { - | ^^^^^^^^^^^^^^^^^^ the trait `From<&A>` is not implemented for `&'static B` +LL | (a, 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 @@ -10,6 +10,12 @@ help: consider introducing a `where` bound, but there might be an alternative be LL | fn f(a: &'static A, b: B) -> (X, X) where &'static B: From<&A> { | ++++++++++++++++++++++++++ -error: aborting due to previous error +error: could not find defining uses + --> $DIR/multiple-def-uses-in-one-fn.rs:7:16 + | +LL | type X = impl Into<&'static A>; + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr index bbe709dccab4e..65bd12d9a9ab9 100644 --- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr @@ -6,7 +6,9 @@ LL | fn g(a: A, b: B) -> (X, X {} @@ -12,8 +12,9 @@ impl Foo<()> for () {} impl Foo for () {} fn foo() -> impl Foo { - //~^ ERROR: the trait bound `(): Foo` is not satisfied [E0277] () + //~^ ERROR: type annotations needed + //~| ERROR: type annotations needed } fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr index 7e24ee644b1ce..294cd07675b88 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr @@ -1,12 +1,22 @@ -error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/nested-tait-inference2.rs:14:13 +error[E0282]: type annotations needed + --> $DIR/nested-tait-inference2.rs:15:5 | -LL | fn foo() -> impl Foo { - | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` +LL | () + | ^^ cannot infer type + +error[E0283]: type annotations needed + --> $DIR/nested-tait-inference2.rs:15:5 + | +LL | () + | ^^ cannot infer type + | +note: multiple `impl`s satisfying `(): Foo<_>` found + --> $DIR/nested-tait-inference2.rs:11:1 | - = help: the following implementations were found: - <() as Foo<()>> - <() as Foo> +LL | impl Foo<()> for () {} + | ^^^^^^^^^^^^^^^^^^^ +LL | impl Foo for () {} + | ^^^^^^^^^^^^^^^^^^^^ error: could not find defining uses --> $DIR/nested-tait-inference2.rs:6:13 @@ -14,6 +24,7 @@ error: could not find defining uses LL | type FooX = impl Debug; | ^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs new file mode 100644 index 0000000000000..e884fa0a48d67 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs @@ -0,0 +1,17 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +use std::fmt::Debug; + +type FooX = impl Debug; +//~^ could not find defining uses + +trait Foo { } + +impl Foo for () { } + +fn foo() -> impl Foo { + () +} + +fn main() { } diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr new file mode 100644 index 0000000000000..6bbed0032b515 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr @@ -0,0 +1,8 @@ +error: could not find defining uses + --> $DIR/nested-tait-inference3.rs:6:13 + | +LL | type FooX = impl Debug; + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.rs b/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.rs index 8787c023eb0c7..fed5ac07c901e 100644 --- a/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.rs +++ b/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.rs @@ -1,8 +1,7 @@ #![feature(type_alias_impl_trait)] - +// check-pass fn main() {} -// don't reveal the concrete type type NoReveal = impl std::fmt::Debug; fn define_no_reveal() -> NoReveal { @@ -10,6 +9,6 @@ fn define_no_reveal() -> NoReveal { } fn no_reveal(x: NoReveal) { - let _: &'static str = x; //~ mismatched types - let _ = x as &'static str; //~ non-primitive cast + let _: &'static str = x; + let _ = x as &'static str; } diff --git a/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr b/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr deleted file mode 100644 index b438f84451649..0000000000000 --- a/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr +++ /dev/null @@ -1,24 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/never_reveal_concrete_type.rs:13:27 - | -LL | type NoReveal = impl std::fmt::Debug; - | -------------------- the found opaque type -... -LL | let _: &'static str = x; - | ------------ ^ expected `&str`, found opaque type - | | - | expected due to this - | - = note: expected reference `&'static str` - found opaque type `impl Debug` - -error[E0605]: non-primitive cast: `impl Debug` as `&'static str` - --> $DIR/never_reveal_concrete_type.rs:14:13 - | -LL | let _ = x as &'static str; - | ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0308, E0605. -For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr b/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr index 67752acb8c9af..d12160a979312 100644 --- a/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr +++ b/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr @@ -5,9 +5,7 @@ LL | pub type Boo = impl ::std::fmt::Debug; | ---------------------- the found opaque type ... LL | let _: &str = bomp(); - | ---- ^^^^^^ expected `&str`, found opaque type - | | - | expected due to this + | ^^^^^^ expected `&str`, found opaque type | = note: expected reference `&str` found opaque type `impl Debug` @@ -18,13 +16,11 @@ error[E0308]: mismatched types LL | pub type Boo = impl ::std::fmt::Debug; | ---------------------- the expected opaque type ... -LL | fn bomp() -> boo::Boo { - | -------- expected `impl Debug` because of return type LL | "" | ^^ expected opaque type, found `&str` | = note: expected opaque type `impl Debug` - found reference `&'static str` + found reference `&str` error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs b/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs index 107cd39457935..cad3ff87749a6 100644 --- a/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs +++ b/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs @@ -8,8 +8,8 @@ type Two = impl Debug; //~^ ERROR `T` doesn't implement `Debug` fn two(t: T) -> Two { - //~^ ERROR non-defining opaque type use in defining scope (t, 4i8) + //~^ ERROR non-defining opaque type use in defining scope } fn three(t: T) -> Two { diff --git a/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr b/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr index 08e49845521c6..aa05f62eb53ea 100644 --- a/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr +++ b/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr @@ -1,8 +1,8 @@ error: non-defining opaque type use in defining scope - --> $DIR/not_a_defining_use.rs:10:27 + --> $DIR/not_a_defining_use.rs:11:5 | -LL | fn two(t: T) -> Two { - | ^^^^^^^^^^^ +LL | (t, 4i8) + | ^^^^^^^^ | note: used non-generic type `u32` for generic parameter --> $DIR/not_a_defining_use.rs:7:13 diff --git a/src/test/ui/type-alias-impl-trait/static-const-types.rs b/src/test/ui/type-alias-impl-trait/static-const-types.rs index 86b685022b20e..748a279e43989 100644 --- a/src/test/ui/type-alias-impl-trait/static-const-types.rs +++ b/src/test/ui/type-alias-impl-trait/static-const-types.rs @@ -1,13 +1,13 @@ #![feature(type_alias_impl_trait)] #![allow(dead_code)] -// FIXME: This should compile, but it currently doesn't +// check-pass use std::fmt::Debug; -type Foo = impl Debug; //~ ERROR could not find defining uses +type Foo = impl Debug; -static FOO1: Foo = 22_u32; //~ ERROR mismatched types -const FOO2: Foo = 22_u32; //~ ERROR mismatched types +static FOO1: Foo = 22_u32; +const FOO2: Foo = 22_u32; fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/static-const-types.stderr b/src/test/ui/type-alias-impl-trait/static-const-types.stderr deleted file mode 100644 index 6f4c2944f7285..0000000000000 --- a/src/test/ui/type-alias-impl-trait/static-const-types.stderr +++ /dev/null @@ -1,33 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/static-const-types.rs:10:20 - | -LL | type Foo = impl Debug; - | ---------- the expected opaque type -LL | -LL | static FOO1: Foo = 22_u32; - | ^^^^^^ expected opaque type, found `u32` - | - = note: expected opaque type `impl Debug` - found type `u32` - -error[E0308]: mismatched types - --> $DIR/static-const-types.rs:11:19 - | -LL | type Foo = impl Debug; - | ---------- the expected opaque type -... -LL | const FOO2: Foo = 22_u32; - | ^^^^^^ expected opaque type, found `u32` - | - = note: expected opaque type `impl Debug` - found type `u32` - -error: could not find defining uses - --> $DIR/static-const-types.rs:8:12 - | -LL | type Foo = impl Debug; - | ^^^^^^^^^^ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs index 51a7b6454c35e..e0d24146179bc 100644 --- a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs +++ b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs @@ -11,7 +11,7 @@ const fn leak_free() -> Bar { const LEAK_FREE: Bar = leak_free(); fn leak_free_test() { - match todo!() { + match LEAK_FREE { LEAK_FREE => (), //~^ `impl Send` cannot be used in patterns _ => (), diff --git a/src/test/ui/type-alias-impl-trait/structural-match.rs b/src/test/ui/type-alias-impl-trait/structural-match.rs index 73558d39ad561..1a2c373bac124 100644 --- a/src/test/ui/type-alias-impl-trait/structural-match.rs +++ b/src/test/ui/type-alias-impl-trait/structural-match.rs @@ -12,7 +12,7 @@ const fn value() -> Foo { const VALUE: Foo = value(); fn test() { - match todo!() { + match VALUE { VALUE => (), //~^ `impl Send` cannot be used in patterns _ => (), diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs index 1a8113848f923..5630e036be34b 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs @@ -1,13 +1,11 @@ #![feature(type_alias_impl_trait)] - +// check-pass // Ensures that `const` items can constrain an opaque `impl Trait`. use std::fmt::Debug; pub type Foo = impl Debug; -//~^ ERROR could not find defining uses const _FOO: Foo = 5; -//~^ ERROR mismatched types [E0308] fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr deleted file mode 100644 index e2567e87ac676..0000000000000 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/type-alias-impl-trait-const.rs:10:19 - | -LL | pub type Foo = impl Debug; - | ---------- the expected opaque type -... -LL | const _FOO: Foo = 5; - | ^ expected opaque type, found integer - | - = note: expected opaque type `impl Debug` - found type `{integer}` - -error: could not find defining uses - --> $DIR/type-alias-impl-trait-const.rs:7:16 - | -LL | pub type Foo = impl Debug; - | ^^^^^^^^^^ - -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/type-alias-impl-trait.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs index d2c8c1f63df1c..70c2ee4278ca2 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(dead_code)] #![allow(unused_assignments)] diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait2.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait2.rs new file mode 100644 index 0000000000000..67f56bcde939a --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait2.rs @@ -0,0 +1,84 @@ +// check-pass + +#![allow(dead_code)] +#![allow(unused_assignments)] +#![allow(unused_variables)] +#![feature(type_alias_impl_trait)] + +fn main() { + assert_eq!(foo().to_string(), "foo"); + assert_eq!(bar1().to_string(), "bar1"); + assert_eq!(bar2().to_string(), "bar2"); + let mut x = bar1(); + x = bar2(); + assert_eq!(my_iter(42u8).collect::>(), vec![42u8]); +} + +use defining_use_scope::*; + +mod defining_use_scope { + // single definition + pub type Foo = impl std::fmt::Display; + + pub fn foo() -> Foo { + "foo" + } + + // two definitions + pub type Bar = impl std::fmt::Display; + + pub fn bar1() -> Bar { + "bar1" + } + + pub fn bar2() -> Bar { + "bar2" + } + + pub type MyIter = impl Iterator; + + pub fn my_iter(t: T) -> MyIter { + std::iter::once(t) + } + + fn my_iter2(t: T) -> MyIter { + std::iter::once(t) + } + + // param names should not have an effect! + fn my_iter3(u: U) -> MyIter { + std::iter::once(u) + } + + // param position should not have an effect! + fn my_iter4(_: U, v: V) -> MyIter { + std::iter::once(v) + } + + // param names should not have an effect! + type MyOtherIter = impl Iterator; + + fn my_other_iter(u: U) -> MyOtherIter { + std::iter::once(u) + } + + trait Trait {} + type GenericBound<'a, T: Trait + 'a> = impl Sized + 'a; + + fn generic_bound<'a, T: Trait + 'a>(t: T) -> GenericBound<'a, T> { + t + } + + mod pass_through { + pub type Passthrough = impl Sized + 'static; + + fn define_passthrough(t: T) -> Passthrough { + t + } + } + + fn use_passthrough(x: pass_through::Passthrough) -> pass_through::Passthrough { + x + } + +} diff --git a/src/test/ui/type-alias-impl-trait/type_of_a_let.rs b/src/test/ui/type-alias-impl-trait/type_of_a_let.rs index 7f8e6127cca3b..4e9d1788b94d8 100644 --- a/src/test/ui/type-alias-impl-trait/type_of_a_let.rs +++ b/src/test/ui/type-alias-impl-trait/type_of_a_let.rs @@ -1,27 +1,20 @@ #![feature(type_alias_impl_trait)] #![allow(dead_code)] -// FIXME This should compile, but it currently doesn't - use std::fmt::Debug; type Foo = impl Debug; -//~^ ERROR: could not find defining uses fn foo1() -> u32 { let x: Foo = 22_u32; - //~^ ERROR: mismatched types [E0308] x - //~^ ERROR: mismatched types [E0308] } fn foo2() -> u32 { let x: Foo = 22_u32; - //~^ ERROR: mismatched types [E0308] let y: Foo = x; - same_type((x, y)); - y - //~^ ERROR: mismatched types [E0308] + same_type((x, y)); //~ ERROR use of moved value + y //~ ERROR use of moved value } fn same_type(x: (T, T)) {} diff --git a/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr b/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr index cac8d6841afda..eccd3f9048f0e 100644 --- a/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr +++ b/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr @@ -1,67 +1,23 @@ -error[E0308]: mismatched types - --> $DIR/type_of_a_let.rs:12:18 +error[E0382]: use of moved value: `x` + --> $DIR/type_of_a_let.rs:16:16 | -LL | type Foo = impl Debug; - | ---------- the expected opaque type -... LL | let x: Foo = 22_u32; - | --- ^^^^^^ expected opaque type, found `u32` - | | - | expected due to this - | - = note: expected opaque type `impl Debug` - found type `u32` - -error[E0308]: mismatched types - --> $DIR/type_of_a_let.rs:14:5 - | -LL | type Foo = impl Debug; - | ---------- the found opaque type -... -LL | fn foo1() -> u32 { - | --- expected `u32` because of return type -... -LL | x - | ^ expected `u32`, found opaque type - | - = note: expected type `u32` - found opaque type `impl Debug` + | - move occurs because `x` has type `impl Debug`, which does not implement the `Copy` trait +LL | let y: Foo = x; + | - value moved here +LL | same_type((x, y)); + | ^ value used here after move -error[E0308]: mismatched types - --> $DIR/type_of_a_let.rs:19:18 - | -LL | type Foo = impl Debug; - | ---------- the expected opaque type -... -LL | let x: Foo = 22_u32; - | --- ^^^^^^ expected opaque type, found `u32` - | | - | expected due to this +error[E0382]: use of moved value: `y` + --> $DIR/type_of_a_let.rs:17:5 | - = note: expected opaque type `impl Debug` - found type `u32` - -error[E0308]: mismatched types - --> $DIR/type_of_a_let.rs:23:5 - | -LL | type Foo = impl Debug; - | ---------- the found opaque type -... -LL | fn foo2() -> u32 { - | --- expected `u32` because of return type -... +LL | let y: Foo = x; + | - move occurs because `y` has type `impl Debug`, which does not implement the `Copy` trait +LL | same_type((x, y)); + | - value moved here LL | y - | ^ expected `u32`, found opaque type - | - = note: expected type `u32` - found opaque type `impl Debug` - -error: could not find defining uses - --> $DIR/type_of_a_let.rs:8:12 - | -LL | type Foo = impl Debug; - | ^^^^^^^^^^ + | ^ value used here after move -error: aborting due to 5 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0382`. diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 7512039a480bb..5407b5e8ed93e 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -32,6 +32,7 @@ pub fn is_min_const_fn<'a, 'tcx>(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv: | ty::PredicateKind::Projection(_) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::OpaqueType(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue, ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {:#?}", predicate), ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {:#?}", predicate), From 9110911353aaee4980c78bcabcb9e5d2aac4c7dd Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 25 Jan 2022 16:02:20 +0000 Subject: [PATCH 09/53] bless --- src/test/ui/nll/issue-52113.stderr | 4 ++-- src/test/ui/nll/ty-outlives/impl-trait-captures.stderr | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/ui/nll/issue-52113.stderr b/src/test/ui/nll/issue-52113.stderr index d82affef26d2f..42ff1866893e6 100644 --- a/src/test/ui/nll/issue-52113.stderr +++ b/src/test/ui/nll/issue-52113.stderr @@ -6,8 +6,8 @@ LL | fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> i | | | lifetime `'a` defined here ... -LL | x - | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` +LL | data.push(value); + | ^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr index 96481810e33a2..42d9f057aaa08 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr +++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -2,9 +2,9 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea --> $DIR/impl-trait-captures.rs:11:5 | LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { - | -- ^^^^^^^^^^^^ - | | - | hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0)) T` captures the anonymous lifetime defined here + | -- hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0)) T` captures the anonymous lifetime defined here +LL | x + | ^ | help: to declare that the `impl Trait` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0))` lifetime bound | From 7bce50c01af576ca0132d9eddcd0ac85e82c9092 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 25 Jan 2022 16:51:42 +0000 Subject: [PATCH 10/53] Register member constraints on the final merged hidden type Previously we did this per hidden type candiate, which didn't always have all the information available. --- compiler/rustc_borrowck/src/type_check/mod.rs | 11 ++++- .../src/type_check/relate_tys.rs | 47 +++++-------------- .../src/infer/canonical/query_response.rs | 2 +- .../rustc_infer/src/infer/nll_relate/mod.rs | 4 +- .../rustc_infer/src/infer/opaque_types.rs | 7 ++- .../rustc_trait_selection/src/opaque_types.rs | 2 +- .../ret-impl-trait-one.nll.stderr | 19 +++++--- .../ret-impl-trait-one.stderr | 19 +++++--- .../ordinary-bounds-unrelated.rs | 1 - .../ordinary-bounds-unrelated.stderr | 16 +------ .../ordinary-bounds-unsuited.rs | 1 - .../ordinary-bounds-unsuited.stderr | 16 +------ ...types_pin_lifetime_impl_trait-async.stderr | 13 ++--- 13 files changed, 62 insertions(+), 96 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index da270be5ef0a8..3667d6bd64009 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -203,9 +203,16 @@ pub(crate) fn type_check<'mir, 'tcx>( ConstraintCategory::OpaqueType, CustomTypeOp::new( |infcx| { - Ok(decl + let res = decl .hidden_type(infcx, &cause, param_env) - .map_err(|e| e.0)?) + .map_err(|e| e.0)?; + infcx.register_member_constraints( + param_env, + opaque_type_key, + res.value.ty, + res.value.span, + ); + Ok(res) }, || "opaque_type_map".to_string(), ), diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index ccf8b44206aa8..aba1dd2bc548c 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -1,5 +1,5 @@ use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; -use rustc_infer::infer::NllRegionVariableOrigin; +use rustc_infer::infer::{InferOk, NllRegionVariableOrigin}; use rustc_infer::traits::ObligationCause; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::relate::TypeRelation; @@ -136,7 +136,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> true } - fn constrain_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool) { + fn register_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool) { let param_env = self.param_env(); let span = self.span(); let def_id = self.type_checker.body.source.def_id().expect_local(); @@ -148,39 +148,18 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> self.category, CustomTypeOp::new( |infcx| { - let (concrete_ty, opaque_type_key) = - match (a.kind(), b.kind(), a_is_expected) { - (ty::Opaque(..), ty::Opaque(..), true) => { - (b, a.expect_opaque_type()) - } - (ty::Opaque(..), ty::Opaque(..), false) => { - (a, b.expect_opaque_type()) - } - (ty::Opaque(..), _, _) => (b, a.expect_opaque_type()), - (_, ty::Opaque(..), _) => (a, b.expect_opaque_type()), - _ => span_bug!( - span, - "no opaque types in constrain_opaque_type {:?}, {:?}", - a, - b - ), - }; - let mut result = self.type_checker.infcx.constrain_opaque_type( - param_env, - opaque_type_key, - concrete_ty, - span, - )?; - result.obligations.push(infcx.opaque_ty_obligation( - a, - b, - a_is_expected, - param_env, - cause, - )); - Ok(result) + Ok(InferOk { + value: (), + obligations: vec![infcx.opaque_ty_obligation( + a, + b, + a_is_expected, + param_env, + cause, + )], + }) }, - || "constrain_opaque_type".to_string(), + || "register_opaque_type".to_string(), ), ) .unwrap(); diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index ecb50dd60973f..20ccad26e8910 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -723,7 +723,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> { true } - fn constrain_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool) { + fn register_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool) { self.obligations.push(self.infcx.opaque_ty_obligation( a, b, diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 5f4555a78f311..3a288516664e3 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -90,7 +90,7 @@ pub trait TypeRelatingDelegate<'tcx> { info: ty::VarianceDiagInfo<'tcx>, ); - fn constrain_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool); + fn register_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool); fn const_equate(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>); @@ -591,7 +591,7 @@ where (_, &ty::Opaque(..)) => (generalize(a, true)?, b), _ => unreachable!(), }; - self.delegate.constrain_opaque_type(a, b, true); + self.delegate.register_opaque_type(a, b, true); trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated"); Ok(a) } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 3ba4b9427251c..dc0ebf23058fd 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -1,5 +1,5 @@ use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use crate::infer::{InferCtxt, InferOk, InferResult}; +use crate::infer::{InferCtxt, InferOk}; use crate::traits::{self, PredicateObligation, PredicateObligations}; use hir::def_id::{DefId, LocalDefId}; use hir::OpaqueTyOrigin; @@ -379,13 +379,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// - `free_region_relations` -- something that can be used to relate /// the free regions (`'a`) that appear in the impl trait. #[instrument(level = "debug", skip(self))] - pub fn constrain_opaque_type( + pub fn register_member_constraints( &self, param_env: ty::ParamEnv<'tcx>, opaque_type_key: OpaqueTypeKey<'tcx>, concrete_ty: Ty<'tcx>, span: Span, - ) -> InferResult<'tcx, ()> { + ) { let def_id = opaque_type_key.def_id; let tcx = self.tcx; @@ -445,7 +445,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ) }, }); - Ok(InferOk { value: (), obligations: vec![] }) } pub fn opaque_ty_obligation( diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 6b0910b475ff2..d3a28c6d3aa35 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -33,7 +33,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { /// purpose of this function is to do that translation. /// /// (*) C1 and C2 were introduced in the comments on - /// `constrain_opaque_type`. Read that comment for more context. + /// `register_member_constraints`. Read that comment for more context. /// /// # Parameters /// diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr index ffb113c1d3367..cdb141c0e3ea2 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr @@ -14,16 +14,21 @@ LL | | } = help: consider adding the following bound: `'a: 'b` error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ret-impl-trait-one.rs:16:65 + --> $DIR/ret-impl-trait-one.rs:16:80 | -LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { - | ^^^^^^^^^^^^^^ +LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { + | ____________________________________--__________________________________________^ + | | | + | | hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here +LL | | +LL | | (a, b) +LL | | } + | |_^ | -note: hidden type `(&'a u8, &' u8)` captures lifetime smaller than the function body - --> $DIR/ret-impl-trait-one.rs:16:65 +help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound | -LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { - | ^^^^^^^^^^^^^^ +LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b { + | ++++ error: aborting due to 2 previous errors diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr index 32b4d18c162d4..2eb3a07059f7b 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr @@ -11,16 +11,21 @@ LL | | } | |_^ ...but data from `a` is returned here error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ret-impl-trait-one.rs:16:65 + --> $DIR/ret-impl-trait-one.rs:16:80 | -LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { - | ^^^^^^^^^^^^^^ +LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { + | ____________________________________--__________________________________________^ + | | | + | | hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here +LL | | +LL | | (a, b) +LL | | } + | |_^ | -note: hidden type `(&'a u8, &' u8)` captures lifetime smaller than the function body - --> $DIR/ret-impl-trait-one.rs:16:65 +help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound | -LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { - | ^^^^^^^^^^^^^^ +LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b { + | ++++ error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs index c4b56cd62534f..47e05bce0f8de 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs @@ -27,7 +27,6 @@ where // ``` if condition() { a } else { b } //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds - //~| ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds } fn condition() -> bool { diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr index 04a5d73e0d378..0e195558badbd 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr @@ -12,20 +12,6 @@ help: to declare that the `impl Trait` captures `'b`, you can add an explicit `' LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b | ++++ -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ordinary-bounds-unrelated.rs:28:33 - | -LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> - | -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here -... -LL | if condition() { a } else { b } - | ^ - | -help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound - | -LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b - | ++++ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs index ff2832c8986e5..321cb8c92a177 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs @@ -30,7 +30,6 @@ fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> // We are forced to pick that '0 = 'e, because only 'e is outlived by *both* 'a and 'b. if condition() { a } else { b } //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds - //~| ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds } fn condition() -> bool { diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr index 018ba3ea5f760..032e88c6d9c13 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr @@ -12,20 +12,6 @@ help: to declare that the `impl Trait` captures `'b`, you can add an explicit `' LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b | ++++ -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ordinary-bounds-unsuited.rs:31:33 - | -LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> - | -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here -... -LL | if condition() { a } else { b } - | ^ - | -help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound - | -LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b - | ++++ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 8ddc3f2c34bd8..570a08cb58768 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -1,14 +1,15 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:37 + --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^^^^^^^ + | - ^^^^^^^^ + | | + | hidden type `Pin<&Foo>` captures the lifetime `'_` as defined here | -note: hidden type `Pin<&' Foo>` captures lifetime smaller than the function body - --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:37 +help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound | -LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^^^^^^^ +LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } + | ++++ error: aborting due to previous error From a745797142f932877695a0a3cd1b452ab67e59df Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Jan 2022 13:02:45 +0000 Subject: [PATCH 11/53] Stop generating inference vars for nested impl trait and let type equality handle it. This means we stop supporting the case where a locally defined trait has only a single impl so we can always use that impl (see nested-tait-inference.rs). --- .../rustc_infer/src/infer/opaque_types.rs | 16 -------- src/test/ui/impl-trait/nested_impl_trait.rs | 2 + .../ui/impl-trait/nested_impl_trait.stderr | 38 +++++++++++++++---- .../type-alias-impl-trait/bound_reduction2.rs | 2 +- .../bound_reduction2.stderr | 11 ++++-- .../nested-tait-inference.rs | 5 ++- .../nested-tait-inference.stderr | 18 +++++++++ .../nested-tait-inference2.rs | 3 +- .../nested-tait-inference2.stderr | 25 ++++-------- 9 files changed, 70 insertions(+), 50 deletions(-) create mode 100644 src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index dc0ebf23058fd..ff636616db49b 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -1,4 +1,3 @@ -use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::{InferCtxt, InferOk}; use crate::traits::{self, PredicateObligation, PredicateObligations}; use hir::def_id::{DefId, LocalDefId}; @@ -604,20 +603,6 @@ struct Instantiator<'a, 'tcx> { } impl<'a, 'tcx> Instantiator<'a, 'tcx> { - #[instrument(level = "trace", skip(self))] - fn instantiate_opaque_types(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if let Some(ty) = self.fold_opaque_ty_new(ty, |infcx, span| { - infcx.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, - span, - }) - }) { - return ty; - } - - ty - } - fn fold_opaque_ty_new( &mut self, ty: Ty<'tcx>, @@ -720,7 +705,6 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { ty::Opaque(def_id2, substs2) if def_id == def_id2 && substs == substs2 => { ty_var } - ty::Opaque(..) => self.instantiate_opaque_types(ty), _ => ty, }, lt_op: |lt| lt, diff --git a/src/test/ui/impl-trait/nested_impl_trait.rs b/src/test/ui/impl-trait/nested_impl_trait.rs index be2c21a7743ce..6eac2dece1f12 100644 --- a/src/test/ui/impl-trait/nested_impl_trait.rs +++ b/src/test/ui/impl-trait/nested_impl_trait.rs @@ -4,6 +4,7 @@ fn fine(x: impl Into) -> impl Into { x } fn bad_in_ret_position(x: impl Into) -> impl Into { x } //~^ ERROR nested `impl Trait` is not allowed +//~| ERROR `impl Into` doesn't implement `Debug` fn bad_in_fn_syntax(x: fn() -> impl Into) {} //~^ ERROR nested `impl Trait` is not allowed @@ -16,6 +17,7 @@ struct X; impl X { fn bad(x: impl Into) -> impl Into { x } //~^ ERROR nested `impl Trait` is not allowed + //~| ERROR `impl Into` doesn't implement `Debug` } fn allowed_in_assoc_type() -> impl Iterator { diff --git a/src/test/ui/impl-trait/nested_impl_trait.stderr b/src/test/ui/impl-trait/nested_impl_trait.stderr index 59c7e4d5f4e92..87ff4ffc4fb17 100644 --- a/src/test/ui/impl-trait/nested_impl_trait.stderr +++ b/src/test/ui/impl-trait/nested_impl_trait.stderr @@ -8,7 +8,7 @@ LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } | outer `impl Trait` error[E0666]: nested `impl Trait` is not allowed - --> $DIR/nested_impl_trait.rs:8:42 + --> $DIR/nested_impl_trait.rs:9:42 | LL | fn bad_in_fn_syntax(x: fn() -> impl Into) {} | ----------^^^^^^^^^^- @@ -17,7 +17,7 @@ LL | fn bad_in_fn_syntax(x: fn() -> impl Into) {} | outer `impl Trait` error[E0666]: nested `impl Trait` is not allowed - --> $DIR/nested_impl_trait.rs:12:37 + --> $DIR/nested_impl_trait.rs:13:37 | LL | fn bad_in_arg_position(_: impl Into) { } | ----------^^^^^^^^^^- @@ -26,7 +26,7 @@ LL | fn bad_in_arg_position(_: impl Into) { } | outer `impl Trait` error[E0666]: nested `impl Trait` is not allowed - --> $DIR/nested_impl_trait.rs:17:44 + --> $DIR/nested_impl_trait.rs:18:44 | LL | fn bad(x: impl Into) -> impl Into { x } | ----------^^^^^^^^^^- @@ -35,18 +35,40 @@ LL | fn bad(x: impl Into) -> impl Into { x } | outer `impl Trait` error[E0562]: `impl Trait` not allowed outside of function and method return types - --> $DIR/nested_impl_trait.rs:8:32 + --> $DIR/nested_impl_trait.rs:9:32 | LL | fn bad_in_fn_syntax(x: fn() -> impl Into) {} | ^^^^^^^^^^^^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and method return types - --> $DIR/nested_impl_trait.rs:25:42 + --> $DIR/nested_impl_trait.rs:27:42 | LL | fn allowed_in_ret_type() -> impl Fn() -> impl Into { | ^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error[E0277]: `impl Into` doesn't implement `Debug` + --> $DIR/nested_impl_trait.rs:5:70 + | +LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } + | ^ `impl Into` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +help: consider further restricting this bound + | +LL | fn bad_in_ret_position(x: impl Into + std::fmt::Debug) -> impl Into { x } + | +++++++++++++++++ + +error[E0277]: `impl Into` doesn't implement `Debug` + --> $DIR/nested_impl_trait.rs:18:58 + | +LL | fn bad(x: impl Into) -> impl Into { x } + | ^ `impl Into` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +help: consider further restricting this bound + | +LL | fn bad(x: impl Into + std::fmt::Debug) -> impl Into { x } + | +++++++++++++++++ + +error: aborting due to 8 previous errors -Some errors have detailed explanations: E0562, E0666. -For more information about an error, try `rustc --explain E0562`. +Some errors have detailed explanations: E0277, E0562, E0666. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs index 2177bf3b1c498..ba780e301edc6 100644 --- a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs +++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs @@ -15,5 +15,5 @@ impl Trait for () {} fn foo_desugared(_: T) -> Foo { () - //~^ ERROR type annotations needed + //~^ ERROR non-defining opaque type use } diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr index 4ff14333c1969..21e79ee36a635 100644 --- a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr +++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr @@ -1,8 +1,14 @@ -error[E0282]: type annotations needed +error: non-defining opaque type use in defining scope --> $DIR/bound_reduction2.rs:17:5 | LL | () - | ^^ cannot infer type + | ^^ + | +note: used non-generic type `::Assoc` for generic parameter + --> $DIR/bound_reduction2.rs:9:10 + | +LL | type Foo = impl Trait; + | ^ error: could not find defining uses --> $DIR/bound_reduction2.rs:9:15 @@ -12,4 +18,3 @@ LL | type Foo = impl Trait; error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs index 075235ec15d4f..78a665d97a0ea 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs @@ -1,18 +1,19 @@ #![feature(type_alias_impl_trait)] #![allow(dead_code)] -// check-pass - use std::fmt::Debug; type FooX = impl Debug; +//~^ ERROR could not find defining uses trait Foo { } impl Foo<()> for () { } fn foo() -> impl Foo { + // FIXME(type-alias-impl-trait): We could probably make this work. () + //~^ ERROR: the trait bound `(): Foo` is not satisfied } fn main() { } diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr new file mode 100644 index 0000000000000..d9585621d2dd2 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/nested-tait-inference.rs:15:5 + | +LL | () + | ^^ the trait `Foo` is not implemented for `()` + | + = help: the following implementations were found: + <() as Foo<()>> + +error: could not find defining uses + --> $DIR/nested-tait-inference.rs:6:13 + | +LL | type FooX = impl Debug; + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs index 365f10f947518..4cbbe01ed5132 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs @@ -13,8 +13,7 @@ impl Foo for () {} fn foo() -> impl Foo { () - //~^ ERROR: type annotations needed - //~| ERROR: type annotations needed + //~^ ERROR: the trait bound `(): Foo` is not satisfied } fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr index 294cd07675b88..e08488287f5cd 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr @@ -1,22 +1,12 @@ -error[E0282]: type annotations needed +error[E0277]: the trait bound `(): Foo` is not satisfied --> $DIR/nested-tait-inference2.rs:15:5 | LL | () - | ^^ cannot infer type - -error[E0283]: type annotations needed - --> $DIR/nested-tait-inference2.rs:15:5 - | -LL | () - | ^^ cannot infer type - | -note: multiple `impl`s satisfying `(): Foo<_>` found - --> $DIR/nested-tait-inference2.rs:11:1 + | ^^ the trait `Foo` is not implemented for `()` | -LL | impl Foo<()> for () {} - | ^^^^^^^^^^^^^^^^^^^ -LL | impl Foo for () {} - | ^^^^^^^^^^^^^^^^^^^^ + = help: the following implementations were found: + <() as Foo<()>> + <() as Foo> error: could not find defining uses --> $DIR/nested-tait-inference2.rs:6:13 @@ -24,7 +14,6 @@ error: could not find defining uses LL | type FooX = impl Debug; | ^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0282, E0283. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0277`. From 38f50d1ecb2adf9f9e6305b22cdee96bd65f9cbe Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Jan 2022 14:47:03 +0000 Subject: [PATCH 12/53] Eagerly merge hidden types. --- .../src/infer/canonical/query_response.rs | 3 +- .../rustc_infer/src/infer/opaque_types.rs | 46 ++++++++++--------- .../src/infer/opaque_types/table.rs | 21 +++++---- compiler/rustc_infer/src/infer/undo_log.rs | 4 +- .../src/traits/fulfill.rs | 2 +- .../src/traits/select/mod.rs | 4 +- src/test/ui/impl-trait/equality.stderr | 9 ++-- src/test/ui/impl-trait/issue-72911.rs | 1 - src/test/ui/impl-trait/issue-72911.stderr | 10 +--- .../ordinary-bounds-unrelated.stderr | 4 +- .../ordinary-bounds-unsuited.stderr | 4 +- ...trait-in-return-position-impl-trait.stderr | 18 +++++--- ...type-err-cause-on-impl-trait-return.stderr | 42 +++++++++++++---- .../ui/type-alias-impl-trait/issue-63279.rs | 1 + .../type-alias-impl-trait/issue-63279.stderr | 16 +++++-- .../type-alias-impl-trait/issue-74280.stderr | 8 +++- .../multiple-def-uses-in-one-fn3.stderr | 11 +++-- 17 files changed, 125 insertions(+), 79 deletions(-) diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 20ccad26e8910..a86471affaa17 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -502,7 +502,8 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let opaque = self.tcx.mk_opaque(key.def_id, substs); for &ty in tys { let ty = substitute_value(self.tcx, &result_subst, ty); - obligations.extend(self.handle_opaque_type(opaque, ty, cause, param_env)?); + obligations + .extend(self.handle_opaque_type(opaque, ty, cause, param_env)?.obligations); } } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index ff636616db49b..cf57270df2920 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -1,5 +1,5 @@ use crate::infer::{InferCtxt, InferOk}; -use crate::traits::{self, PredicateObligation, PredicateObligations}; +use crate::traits::{self, PredicateObligation}; use hir::def_id::{DefId, LocalDefId}; use hir::OpaqueTyOrigin; use rustc_data_structures::sync::Lrc; @@ -20,6 +20,8 @@ mod table; pub use table::{OpaqueTypeStorage, OpaqueTypeTable}; +use super::InferResult; + /// Information about the opaque types whose values we /// are inferring in this function (these are the `impl Trait` that /// appear in the return type). @@ -152,11 +154,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { opaque: Ty<'tcx>, cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, - ) -> Option>> { - let mut obligations = vec![]; - let value = Instantiator { infcx: self, cause, param_env, obligations: &mut obligations } - .fold_opaque_ty_new(opaque, |_, _| ty)?; - Some(InferOk { value, obligations }) + ) -> Option> { + Instantiator { infcx: self, cause, param_env }.fold_opaque_ty_new(opaque, |_, _| ty) } pub fn handle_opaque_type( @@ -165,9 +164,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { b: Ty<'tcx>, cause: &ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, - ) -> Result, TypeError<'tcx>> { + ) -> InferResult<'tcx, ()> { if a.references_error() || b.references_error() { - return Ok(vec![]); + return Ok(InferOk { value: (), obligations: vec![] }); } if self.defining_use_anchor.is_some() { let process = |a: Ty<'tcx>, b: Ty<'tcx>| { @@ -175,12 +174,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { return None; } self.instantiate_opaque_types(b, a, cause.clone(), param_env) - .map(|res| res.obligations) }; if let Some(res) = process(a, b) { - Ok(res) + res } else if let Some(res) = process(b, a) { - Ok(res) + res } else { // Rerun equality check, but this time error out due to // different types. @@ -205,13 +203,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }; let key = opaque_type.expect_opaque_type(); let origin = self.opaque_ty_origin_unchecked(key.def_id, cause.span); - self.inner.borrow_mut().opaque_types().register( + let prev = self.inner.borrow_mut().opaque_types().register( key, opaque_type, OpaqueHiddenType { ty: hidden_ty, span: cause.span }, origin, ); - Ok(vec![]) + match prev { + Some(prev) => self.at(cause, param_env).eq(prev, hidden_ty), + None => Ok(InferOk { value: (), obligations: vec![] }), + } } } @@ -599,7 +600,6 @@ struct Instantiator<'a, 'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, - obligations: &'a mut PredicateObligations<'tcx>, } impl<'a, 'tcx> Instantiator<'a, 'tcx> { @@ -607,7 +607,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { &mut self, ty: Ty<'tcx>, mk_ty: impl FnOnce(&InferCtxt<'_, 'tcx>, Span) -> Ty<'tcx>, - ) -> Option> { + ) -> Option> { // Check that this is `impl Trait` type is // declared by `parent_def_id` -- i.e., one whose // value we are inferring. At present, this is @@ -659,7 +659,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { opaque_type_key: OpaqueTypeKey<'tcx>, origin: hir::OpaqueTyOrigin, mk_ty: impl FnOnce(&InferCtxt<'_, 'tcx>, Span) -> Ty<'tcx>, - ) -> Ty<'tcx> { + ) -> InferResult<'tcx, ()> { let infcx = self.infcx; let tcx = infcx.tcx; let OpaqueTypeKey { def_id, substs } = opaque_type_key; @@ -673,12 +673,16 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { // Foo, impl Bar)`. let span = self.cause.span; - self.infcx.inner.borrow_mut().opaque_types().register( + let mut obligations = vec![]; + let prev = self.infcx.inner.borrow_mut().opaque_types().register( OpaqueTypeKey { def_id, substs }, ty, OpaqueHiddenType { ty: ty_var, span }, origin, ); + if let Some(prev) = prev { + obligations = self.infcx.at(&self.cause, self.param_env).eq(prev, ty_var)?.obligations; + } debug!("generated new type inference var {:?}", ty_var.kind()); @@ -698,7 +702,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { projection_ty, self.cause.clone(), 0, - &mut self.obligations, + &mut obligations, ), // Replace all other mentions of the same opaque type with the hidden type, // as the bounds must hold on the hidden type after all. @@ -714,19 +718,19 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() { if projection.term.references_error() { // No point on adding these obligations since there's a type error involved. - return tcx.ty_error(); + return Ok(InferOk { value: (), obligations: vec![] }); } trace!("{:#?}", projection.term); } // Require that the predicate holds for the concrete type. debug!(?predicate); - self.obligations.push(traits::Obligation::new( + obligations.push(traits::Obligation::new( self.cause.clone(), self.param_env, predicate, )); } - ty_var + Ok(InferOk { value: (), obligations }) } } diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs index dc47272c4fe05..1895c1a85c7cc 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/table.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -18,14 +18,14 @@ pub struct OpaqueTypeStorage<'tcx> { impl<'tcx> OpaqueTypeStorage<'tcx> { #[instrument(level = "debug")] - pub(crate) fn remove(&mut self, key: OpaqueTypeKey<'tcx>, idx: usize) { - if idx == 0 { + pub(crate) fn remove(&mut self, key: OpaqueTypeKey<'tcx>, idx: Option>) { + if let Some(idx) = idx { + self.opaque_types.get_mut(&key).unwrap().hidden_types[0] = idx; + } else { match self.opaque_types.remove(&key) { None => bug!("reverted opaque type inference that was never registered: {:?}", key), Some(_) => {} } - } else { - self.opaque_types.get_mut(&key).unwrap().hidden_types.drain(idx..); } } @@ -75,14 +75,17 @@ impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> { opaque_type: Ty<'tcx>, ty: OpaqueHiddenType<'tcx>, origin: OpaqueTyOrigin, - ) { + ) -> Option> { if let Some(decl) = self.storage.opaque_types.get_mut(&key) { - decl.hidden_types.push(ty); - self.undo_log.push(UndoLog::OpaqueTypes(key, decl.hidden_types.len())); - return; + assert_eq!(decl.hidden_types.len(), 1); + let prev = decl.hidden_types[0]; + decl.hidden_types = vec![ty]; + self.undo_log.push(UndoLog::OpaqueTypes(key, Some(prev))); + return Some(prev.ty); } let decl = OpaqueTypeDecl { opaque_type, hidden_types: vec![ty], origin }; self.storage.opaque_types.insert(key, decl); - self.undo_log.push(UndoLog::OpaqueTypes(key, 0)); + self.undo_log.push(UndoLog::OpaqueTypes(key, None)); + None } } diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs index 8f4abfde3010a..02b15baf8fb2d 100644 --- a/compiler/rustc_infer/src/infer/undo_log.rs +++ b/compiler/rustc_infer/src/infer/undo_log.rs @@ -11,6 +11,8 @@ use crate::{ traits, }; +use super::opaque_types::OpaqueHiddenType; + pub struct Snapshot<'tcx> { pub(crate) undo_len: usize, _marker: PhantomData<&'tcx ()>, @@ -18,7 +20,7 @@ pub struct Snapshot<'tcx> { /// Records the "undo" data for a single operation that affects some form of inference variable. pub(crate) enum UndoLog<'tcx> { - OpaqueTypes(OpaqueTypeKey<'tcx>, usize), + OpaqueTypes(OpaqueTypeKey<'tcx>, Option>), TypeVariables(type_variable::UndoLog<'tcx>), ConstUnificationTable(sv::UndoLog>>), IntUnificationTable(sv::UndoLog>), diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 68dd1cd261683..274f8a3ef79fa 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -652,7 +652,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { &obligation.cause, obligation.param_env, ) { - Ok(value) => ProcessResult::Changed(mk_pending(value)), + Ok(value) => ProcessResult::Changed(mk_pending(value.obligations)), Err(err) => ProcessResult::Error(FulfillmentErrorCode::CodeSubtypeError( ExpectedFound::new(true, a, b), err, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 3b99183d8eb1f..35818786cbbf1 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -705,8 +705,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &obligation.cause, obligation.param_env, ) { - Ok(obligations) => { - self.evaluate_predicates_recursively(previous_stack, obligations) + Ok(res) => { + self.evaluate_predicates_recursively(previous_stack, res.obligations) } Err(_) => Ok(EvaluatedToErr), } diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index f79411c1003eb..4032fbbceba4c 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -11,11 +11,14 @@ LL | #![feature(specialization)] error[E0308]: mismatched types --> $DIR/equality.rs:15:5 | -LL | return 1_i32; - | ----- type expected due to this -LL | } +LL | fn two(x: bool) -> impl Foo { + | -------- the expected opaque type +... LL | 0_u32 | ^^^^^ expected `i32`, found `u32` + | + = note: expected opaque type `impl Foo` + found type `u32` error[E0277]: cannot add `impl Foo` to `u32` --> $DIR/equality.rs:24:11 diff --git a/src/test/ui/impl-trait/issue-72911.rs b/src/test/ui/impl-trait/issue-72911.rs index d556e968f34e5..cf2c8b7e41540 100644 --- a/src/test/ui/impl-trait/issue-72911.rs +++ b/src/test/ui/impl-trait/issue-72911.rs @@ -16,7 +16,6 @@ fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator fn lint_files() -> impl Iterator { //~^ ERROR: failed to resolve - //~| ERROR `()` is not an iterator unimplemented!() } diff --git a/src/test/ui/impl-trait/issue-72911.stderr b/src/test/ui/impl-trait/issue-72911.stderr index 51648e6154dc3..4a990286d966d 100644 --- a/src/test/ui/impl-trait/issue-72911.stderr +++ b/src/test/ui/impl-trait/issue-72911.stderr @@ -18,15 +18,7 @@ LL | pub fn gather_all() -> impl Iterator { | = help: the trait `Iterator` is not implemented for `()` -error[E0277]: `()` is not an iterator - --> $DIR/issue-72911.rs:17:20 - | -LL | fn lint_files() -> impl Iterator { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator - | - = help: the trait `Iterator` is not implemented for `()` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0433. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr index 0e195558badbd..15476c706a7f2 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr @@ -1,11 +1,11 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ordinary-bounds-unrelated.rs:28:22 + --> $DIR/ordinary-bounds-unrelated.rs:28:33 | LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> | -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here ... LL | if condition() { a } else { b } - | ^ + | ^ | help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound | diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr index 032e88c6d9c13..7315aa8e9d478 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr @@ -1,11 +1,11 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ordinary-bounds-unsuited.rs:31:22 + --> $DIR/ordinary-bounds-unsuited.rs:31:33 | LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> | -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here ... LL | if condition() { a } else { b } - | ^ + | ^ | help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound | diff --git a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr index 4b4116887dc27..b2f7166f0ae3a 100644 --- a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr +++ b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr @@ -1,20 +1,26 @@ error[E0308]: mismatched types --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:36:5 | -LL | return A; - | - type expected due to this -LL | } +LL | fn can() -> impl NotObjectSafe { + | ------------------ the expected opaque type +... LL | B | ^ expected struct `A`, found struct `B` + | + = note: expected opaque type `impl NotObjectSafe` + found struct `B` error[E0308]: mismatched types --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:43:5 | -LL | return A; - | - type expected due to this -LL | } +LL | fn cat() -> impl ObjectSafe { + | --------------- the expected opaque type +... LL | B | ^ expected struct `A`, found struct `B` + | + = note: expected opaque type `impl ObjectSafe` + found struct `B` error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr index eb0d3a52a4eb7..db0d446e559a3 100644 --- a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr +++ b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr @@ -1,31 +1,41 @@ error[E0308]: mismatched types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:5:5 | -LL | return 0i32; - | ---- type expected due to this -LL | } +LL | fn foo() -> impl std::fmt::Display { + | ---------------------- the expected opaque type +... LL | 1u32 | ^^^^ expected `i32`, found `u32` + | + = note: expected opaque type `impl std::fmt::Display` + found type `u32` error[E0308]: mismatched types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:12:16 | -LL | return 0i32; - | ---- type expected due to this -LL | } else { +LL | fn bar() -> impl std::fmt::Display { + | ---------------------- the expected opaque type +... LL | return 1u32; | ^^^^ expected `i32`, found `u32` + | + = note: expected opaque type `impl std::fmt::Display` + found type `u32` error[E0308]: mismatched types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:17:5 | +LL | fn baz() -> impl std::fmt::Display { + | ---------------------- the expected opaque type LL | / if false { LL | | return 0i32; - | | ---- type expected due to this LL | | } else { LL | | 1u32 LL | | } | |_____^ expected `i32`, found `u32` + | + = note: expected opaque type `impl std::fmt::Display` + found type `u32` error[E0308]: `if` and `else` have incompatible types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:28:9 @@ -53,36 +63,48 @@ LL ~ Box::new(1u32) error[E0308]: mismatched types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:33:5 | +LL | fn bat() -> impl std::fmt::Display { + | ---------------------- the expected opaque type LL | / match 13 { LL | | 0 => return 0i32, - | | ---- type expected due to this LL | | _ => 1u32, LL | | } | |_____^ expected `i32`, found `u32` + | + = note: expected opaque type `impl std::fmt::Display` + found type `u32` error[E0308]: mismatched types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:40:5 | +LL | fn can() -> impl std::fmt::Display { + | ---------------------- the expected opaque type LL | / match 13 { LL | | 0 => return 0i32, - | | ---- type expected due to this LL | | 1 => 1u32, LL | | _ => 2u32, LL | | } | |_____^ expected `i32`, found `u32` + | + = note: expected opaque type `impl std::fmt::Display` + found type `u32` error[E0308]: mismatched types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:48:5 | +LL | fn cat() -> impl std::fmt::Display { + | ---------------------- the expected opaque type LL | / match 13 { LL | | 0 => { LL | | return 0i32; - | | ---- type expected due to this LL | | } ... | LL | | } LL | | } | |_____^ expected `i32`, found `u32` + | + = note: expected opaque type `impl std::fmt::Display` + found type `u32` error[E0308]: `match` arms have incompatible types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:61:14 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 3d20b7e37190d..e09e1a3afed69 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63279.rs +++ b/src/test/ui/type-alias-impl-trait/issue-63279.rs @@ -8,6 +8,7 @@ type Closure = impl FnOnce(); fn c() -> Closure { || -> Closure { || () } //~^ ERROR: mismatched types + //~| ERROR: mismatched types //~| ERROR: expected a `FnOnce<()>` closure, found `()` } 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 385e816eebf52..810c99c84bc4c 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63279.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-63279.stderr @@ -15,10 +15,18 @@ LL | || -> Closure { || () } | = note: expected unit type `()` found closure `[closure@$DIR/issue-63279.rs:9:21: 9:26]` -help: you might have meant to return this value + +error[E0308]: mismatched types + --> $DIR/issue-63279.rs:9:5 + | +LL | type Closure = impl FnOnce(); + | ------------- the expected opaque type +... +LL | || -> Closure { || () } + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found closure | -LL | || -> Closure { return || (); } - | ++++++ + + = note: expected opaque type `impl FnOnce()` + found closure `[closure@$DIR/issue-63279.rs:9:5: 9:28]` error: could not find defining uses --> $DIR/issue-63279.rs:5:16 @@ -26,7 +34,7 @@ error: could not find defining uses LL | type Closure = impl FnOnce(); | ^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. 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 475a005223426..db8c5b7a72bef 100644 --- a/src/test/ui/type-alias-impl-trait/issue-74280.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-74280.stderr @@ -1,10 +1,14 @@ error[E0308]: mismatched types --> $DIR/issue-74280.rs:10:5 | -LL | let y = || -> Test { () }; - | -- type expected due to this +LL | type Test = impl Copy; + | --------- the expected opaque type +... LL | 7 | ^ expected `()`, found integer + | + = note: expected opaque type `impl Copy` + found type `{integer}` error: could not find defining uses --> $DIR/issue-74280.rs:5:13 diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr index 65bd12d9a9ab9..20da37ec9a186 100644 --- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr @@ -1,17 +1,18 @@ error[E0308]: mismatched types --> $DIR/multiple-def-uses-in-one-fn3.rs:14:9 | +LL | type X = impl ToString; + | ------------- the expected opaque type +... LL | fn g(a: A, b: B) -> (X, X) { | - - found type parameter | | | expected type parameter LL | (a, b) - | - ^ expected type parameter `A`, found type parameter `B` - | | - | type expected due to this + | ^ expected type parameter `A`, found type parameter `B` | - = note: expected type parameter `A` - found type parameter `B` + = note: expected opaque type `impl ToString` + found type parameter `B` = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters From edaf9625fbc4fc3bb4f8eb049112840e68d79351 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Jan 2022 15:10:01 +0000 Subject: [PATCH 13/53] Clean up leftovers from eager hidden type merging --- compiler/rustc_borrowck/src/type_check/mod.rs | 51 ++++++++---------- .../src/infer/canonical/query_response.rs | 13 ++--- .../rustc_infer/src/infer/opaque_types.rs | 52 +------------------ .../src/infer/opaque_types/table.rs | 10 ++-- compiler/rustc_middle/src/infer/canonical.rs | 2 +- compiler/rustc_typeck/src/check/mod.rs | 15 ------ 6 files changed, 34 insertions(+), 109 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 3667d6bd64009..6559ded5816d2 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -18,7 +18,9 @@ use rustc_index::vec::{Idx, IndexVec}; use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime, NllRegionVariableOrigin}; +use rustc_infer::infer::{ + InferCtxt, InferOk, LateBoundRegionConversionTime, NllRegionVariableOrigin, +}; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::AssertKind; @@ -194,31 +196,24 @@ pub(crate) fn type_check<'mir, 'tcx>( let opaque_type_values = opaque_type_values .into_iter() .filter_map(|(opaque_type_key, decl)| { - let def_id = body.source.def_id().expect_local(); - let body_id = cx.tcx().hir().local_def_id_to_hir_id(def_id); - let cause = ObligationCause::misc(body.span, body_id); - let hidden = cx - .fully_perform_op( - Locations::All(body.span), - ConstraintCategory::OpaqueType, - CustomTypeOp::new( - |infcx| { - let res = decl - .hidden_type(infcx, &cause, param_env) - .map_err(|e| e.0)?; - infcx.register_member_constraints( - param_env, - opaque_type_key, - res.value.ty, - res.value.span, - ); - Ok(res) - }, - || "opaque_type_map".to_string(), - ), - ) - .unwrap(); - let mut hidden_type = infcx.resolve_vars_if_possible(hidden.ty); + cx.fully_perform_op( + Locations::All(body.span), + ConstraintCategory::OpaqueType, + CustomTypeOp::new( + |infcx| { + infcx.register_member_constraints( + param_env, + opaque_type_key, + decl.hidden_type.ty, + decl.hidden_type.span, + ); + Ok(InferOk { value: (), obligations: vec![] }) + }, + || "opaque_type_map".to_string(), + ), + ) + .unwrap(); + let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type.ty); trace!( "finalized opaque type {:?} to {:#?}", opaque_type_key, @@ -226,7 +221,7 @@ pub(crate) fn type_check<'mir, 'tcx>( ); if hidden_type.has_infer_types_or_consts() { infcx.tcx.sess.delay_span_bug( - hidden.span, + decl.hidden_type.span, &format!("could not resolve {:#?}", hidden_type.kind()), ); hidden_type = infcx.tcx.ty_error(); @@ -263,7 +258,7 @@ pub(crate) fn type_check<'mir, 'tcx>( ); None } else { - Some((opaque_type_key, (hidden_type, hidden.span, decl.origin))) + Some((opaque_type_key, (hidden_type, decl.hidden_type.span, decl.origin))) } }) .collect(); diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index a86471affaa17..18a1120051efe 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -146,13 +146,13 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { }) } - fn take_opaque_types_for_query_response(&self) -> Vec<(OpaqueTypeKey<'tcx>, Vec>)> { + fn take_opaque_types_for_query_response(&self) -> Vec<(OpaqueTypeKey<'tcx>, Ty<'tcx>)> { self.inner .borrow_mut() .opaque_type_storage .take_opaque_types() .into_iter() - .map(|(k, v)| (k, v.hidden_types.into_iter().map(|ht| ht.ty).collect())) + .map(|(k, v)| (k, v.hidden_type.ty)) .collect() } @@ -497,14 +497,11 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let mut obligations = vec![]; // Carry all newly resolved opaque types to the caller's scope - for (key, tys) in &query_response.value.opaque_types { + for &(key, ty) in &query_response.value.opaque_types { let substs = substitute_value(self.tcx, &result_subst, key.substs); let opaque = self.tcx.mk_opaque(key.def_id, substs); - for &ty in tys { - let ty = substitute_value(self.tcx, &result_subst, ty); - obligations - .extend(self.handle_opaque_type(opaque, ty, cause, param_env)?.obligations); - } + let ty = substitute_value(self.tcx, &result_subst, ty); + obligations.extend(self.handle_opaque_type(opaque, ty, cause, param_env)?.obligations); } Ok(InferOk { value: result_subst, obligations }) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index cf57270df2920..748fe1379cd62 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -6,7 +6,6 @@ use rustc_data_structures::sync::Lrc; use rustc_data_structures::vec_map::VecMap; use rustc_hir as hir; use rustc_middle::traits::ObligationCause; -use rustc_middle::ty::error::TypeError; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::subst::{GenericArgKind, Subst}; use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitor}; @@ -33,61 +32,12 @@ pub struct OpaqueTypeDecl<'tcx> { /// The hidden types that have been inferred for this opaque type. /// There can be multiple, but they are all `lub`ed together at the end /// to obtain the canonical hidden type. - pub hidden_types: Vec>, + pub hidden_type: OpaqueHiddenType<'tcx>, /// The origin of the opaque type. pub origin: hir::OpaqueTyOrigin, } -impl<'tcx> OpaqueTypeDecl<'tcx> { - pub fn hidden_type( - &self, - infcx: &InferCtxt<'_, 'tcx>, - cause: &ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ) -> Result< - InferOk<'tcx, OpaqueHiddenType<'tcx>>, - (TypeError<'tcx>, OpaqueHiddenType<'tcx>, OpaqueHiddenType<'tcx>), - > { - let mut value = self.hidden_types[0]; - let mut obligations = vec![]; - let mut error: Option<(_, _, OpaqueHiddenType<'tcx>)> = None; - for &next in self.hidden_types[1..].iter() { - // FIXME: make use of the spans to get nicer diagnostics! - let res = match infcx.at(cause, param_env).eq(value.ty, next.ty) { - Ok(res) => res, - Err(e) => { - // Try to improve the span. Sometimes we have dummy spans, sometimes we are pointing - // at an if/match instead of at the arm that gave us the type, but later spans point - // to the right thing. - if let Some((_, _, old)) = &mut error { - old.span = old.span.substitute_dummy(next.span); - // Shrink the span if possible - if old.span.contains(next.span) { - old.span = next.span; - } - } else { - let mut next = next; - next.span = next.span.substitute_dummy(cause.span(infcx.tcx)); - error = Some((e, value, next)); - } - continue; - } - }; - obligations.extend(res.obligations); - value.span = value.span.substitute_dummy(next.span); - // Shrink the span if possible - if value.span.contains(next.span) { - value.span = next.span; - } - } - match error { - None => Ok(InferOk { value, obligations }), - Some(e) => Err(e), - } - } -} - #[derive(Copy, Clone, Debug, TypeFoldable)] pub struct OpaqueHiddenType<'tcx> { /// The span of this particular definition of the opaque type. So diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs index 1895c1a85c7cc..7f16a2f533226 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/table.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -20,7 +20,7 @@ impl<'tcx> OpaqueTypeStorage<'tcx> { #[instrument(level = "debug")] pub(crate) fn remove(&mut self, key: OpaqueTypeKey<'tcx>, idx: Option>) { if let Some(idx) = idx { - self.opaque_types.get_mut(&key).unwrap().hidden_types[0] = idx; + self.opaque_types.get_mut(&key).unwrap().hidden_type = idx; } else { match self.opaque_types.remove(&key) { None => bug!("reverted opaque type inference that was never registered: {:?}", key), @@ -73,17 +73,15 @@ impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> { &mut self, key: OpaqueTypeKey<'tcx>, opaque_type: Ty<'tcx>, - ty: OpaqueHiddenType<'tcx>, + hidden_type: OpaqueHiddenType<'tcx>, origin: OpaqueTyOrigin, ) -> Option> { if let Some(decl) = self.storage.opaque_types.get_mut(&key) { - assert_eq!(decl.hidden_types.len(), 1); - let prev = decl.hidden_types[0]; - decl.hidden_types = vec![ty]; + let prev = std::mem::replace(&mut decl.hidden_type, hidden_type); self.undo_log.push(UndoLog::OpaqueTypes(key, Some(prev))); return Some(prev.ty); } - let decl = OpaqueTypeDecl { opaque_type, hidden_types: vec![ty], origin }; + let decl = OpaqueTypeDecl { opaque_type, hidden_type, origin }; self.storage.opaque_types.insert(key, decl); self.undo_log.push(UndoLog::OpaqueTypes(key, None)); None diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index cc83010580f98..654ec022b604f 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -180,7 +180,7 @@ pub struct QueryResponse<'tcx, R> { pub certainty: Certainty, /// List of opaque types for which we figured out a hidden type /// during the evaluation of the query. - pub opaque_types: Vec<(OpaqueTypeKey<'tcx>, Vec>)>, + pub opaque_types: Vec<(OpaqueTypeKey<'tcx>, Ty<'tcx>)>, pub value: R, } diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 5094806e75f4a..d4be3889a7ae7 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -99,8 +99,6 @@ pub use diverges::Diverges; pub use expectation::Expectation; pub use fn_ctxt::*; pub use inherited::{Inherited, InheritedBuilder}; -use rustc_infer::traits::ObligationCause; -use traits::ObligationCauseCode::MiscObligation; use crate::astconv::AstConv; use crate::check::gather_locals::GatherLocalsVisitor; @@ -474,19 +472,6 @@ fn typeck_with_fallback<'tcx>( fcx.require_type_is_sized(ty, span, code); } - let opaque_types = fcx.infcx.inner.borrow_mut().opaque_type_storage.opaque_types(); - for (_, decl) in opaque_types { - let cause = ObligationCause::new(body.value.span, id, MiscObligation); - if let Err((err, expected, actual)) = - decl.hidden_type(&fcx.infcx, &cause, fcx.param_env) - { - let cause = ObligationCause::new(actual.span, id, MiscObligation); - fcx.report_mismatched_types(&cause, expected.ty, actual.ty, err) - .span_label(expected.span, "type expected due to this") - .emit(); - } - } - fcx.select_all_obligations_or_error(); if fn_sig.is_some() { From 64c5b9a3d6f26659e0bd388fbb00cd92d888178d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Jan 2022 15:49:43 +0000 Subject: [PATCH 14/53] Add backcompat hack to support ```rust fn foo() -> impl MyTrait { panic!(); MyStruct } struct MyStruct; trait MyTrait {} impl MyTrait for MyStruct {} ``` --- compiler/rustc_middle/src/ty/context.rs | 11 +++++++--- compiler/rustc_typeck/src/check/writeback.rs | 10 +++++++-- compiler/rustc_typeck/src/collect/type_of.rs | 23 ++++++++++---------- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5dae4b9e4c971..694b7d2b817cf 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -30,6 +30,7 @@ use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal}; +use rustc_data_structures::vec_map::VecMap; use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -464,9 +465,13 @@ pub struct TypeckResults<'tcx> { /// this field will be set to `Some(ErrorReported)`. pub tainted_by_errors: Option, - /// All the opaque types that are restricted to concrete types - /// by this function. - pub concrete_opaque_types: FxHashSet, + /// All the opaque types that have hidden types set + /// by this function. For return-position-impl-trait we also store the + /// type here, so that mir-borrowck can figure out hidden types, + /// even if they are only set in dead code (which doesn't show up in MIR). + /// For type-alias-impl-trait, this map is only used to prevent query cycles, + /// so the hidden types are all `None`. + pub concrete_opaque_types: VecMap>>, /// Tracks the minimum captures required for a closure; /// see `MinCaptureInformationMap` for more details. diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index f97fedd9a6dab..e04c1423cdac8 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -499,8 +499,14 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn visit_opaque_types(&mut self) { let opaque_types = self.fcx.infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); - for (opaque_type_key, _) in opaque_types { - self.typeck_results.concrete_opaque_types.insert(opaque_type_key.def_id); + for (opaque_type_key, decl) in opaque_types { + let hidden_type = match decl.origin { + hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) => { + Some(self.resolve(decl.hidden_type.ty, &decl.hidden_type.span)) + } + hir::OpaqueTyOrigin::TyAlias => None, + }; + self.typeck_results.concrete_opaque_types.insert(opaque_type_key.def_id, hidden_type); } } diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index ce2f486bb7043..81faacd4da559 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -389,21 +389,22 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { .get_value_matching(|(key, _)| key.def_id == def_id.to_def_id()) .copied() .unwrap_or_else(|| { - if let Some(ErrorReported) = - tcx.typeck(owner).tainted_by_errors - { + let table = tcx.typeck(owner); + if let Some(ErrorReported) = table.tainted_by_errors { // Some error in the // owner fn prevented us from populating // the `concrete_opaque_types` table. tcx.ty_error() } else { - // We failed to resolve the opaque type or it - // resolves to itself. We interpret this as the - // no values of the hidden type ever being constructed, - // so we can just make the hidden type be `!`. - // For backwards compatibility reasons, we fall back to - // `()` until we the diverging default is changed. - tcx.mk_diverging_default() + table.concrete_opaque_types.get(&def_id.to_def_id()).copied().unwrap_or_else(|| { + // We failed to resolve the opaque type or it + // resolves to itself. We interpret this as the + // no values of the hidden type ever being constructed, + // so we can just make the hidden type be `!`. + // For backwards compatibility reasons, we fall back to + // `()` until we the diverging default is changed. + Some(tcx.mk_diverging_default()) + }).expect("RPIT always have a hidden type from typeck") } }); debug!("concrete_ty = {:?}", concrete_ty); @@ -597,7 +598,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { } // Calling `mir_borrowck` can lead to cycle errors through // const-checking, avoid calling it if we don't have to. - if !self.tcx.typeck(def_id).concrete_opaque_types.contains(&self.def_id) { + if self.tcx.typeck(def_id).concrete_opaque_types.get(&self.def_id).is_none() { debug!("no constraints in typeck results"); return; } From 7795f6233ccc2319ecca3605442ddceb279ee815 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Jan 2022 16:19:49 +0000 Subject: [PATCH 15/53] Add explanation for early abort in TAIT hidden type computation --- compiler/rustc_typeck/src/collect/type_of.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 81faacd4da559..4b61e21c0e0cf 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -598,6 +598,15 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { } // Calling `mir_borrowck` can lead to cycle errors through // const-checking, avoid calling it if we don't have to. + // ```rust + // type Foo = impl Fn() -> usize; // when computing type for this + // const fn bar() -> Foo { + // || 0usize + // } + // const BAZR: Foo = bar(); // we would mir-borrowck this, causing cycles + // // because we again need to reveal `Foo` so we can check whether the + // // constant does not contain interior mutability. + // ``` if self.tcx.typeck(def_id).concrete_opaque_types.get(&self.def_id).is_none() { debug!("no constraints in typeck results"); return; From 77aacc1768788970ed911582434ecd54a9f4d790 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Jan 2022 16:33:16 +0000 Subject: [PATCH 16/53] Test recursive TAIT declarations --- ...alias-impl-trait-declaration-too-subtle.rs | 29 +++++++++++++++ ...s-impl-trait-declaration-too-subtle.stderr | 14 +++++++ ...rsive-type-alias-impl-trait-declaration.rs | 37 +++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs create mode 100644 src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr create mode 100644 src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs new file mode 100644 index 0000000000000..162a26593c7f6 --- /dev/null +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs @@ -0,0 +1,29 @@ +#![feature(type_alias_impl_trait)] + +mod a { + type Foo = impl PartialEq<(Foo, i32)>; + //~^ ERROR could not find defining uses + + struct Bar; + + impl PartialEq<(Bar, i32)> for Bar { + fn eq(&self, _other: &(Foo, i32)) -> bool { + true + } + } +} + +mod b { + type Foo = impl PartialEq<(Foo, i32)>; + //~^ ERROR could not find defining uses + + struct Bar; + + impl PartialEq<(Foo, i32)> for Bar { + fn eq(&self, _other: &(Bar, i32)) -> bool { + true + } + } +} + +fn main() {} diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr new file mode 100644 index 0000000000000..71c4e3f5949e1 --- /dev/null +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr @@ -0,0 +1,14 @@ +error: could not find defining uses + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:4:16 + | +LL | type Foo = impl PartialEq<(Foo, i32)>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: could not find defining uses + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:17:16 + | +LL | type Foo = impl PartialEq<(Foo, i32)>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs new file mode 100644 index 0000000000000..bdabc13c36a96 --- /dev/null +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs @@ -0,0 +1,37 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +mod direct { + type Foo = impl PartialEq<(Foo, i32)>; + + struct Bar; + + impl PartialEq<(Foo, i32)> for Bar { + fn eq(&self, _other: &(Foo, i32)) -> bool { + true + } + } + + fn foo() -> Foo { + Bar + } +} + +mod indirect { + type Foo = impl PartialEq<(Foo, i32)>; + + struct Bar; + + impl PartialEq<(Bar, i32)> for Bar { + fn eq(&self, _other: &(Bar, i32)) -> bool { + true + } + } + + fn foo() -> Foo { + Bar + } +} + +fn main() {} From cbfd7362924a97caef6e29dd5db7569764c8d507 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Jan 2022 16:33:28 +0000 Subject: [PATCH 17/53] Update an outdated test explanation --- src/test/ui/type-alias-impl-trait/fallback.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/type-alias-impl-trait/fallback.rs b/src/test/ui/type-alias-impl-trait/fallback.rs index fe1ca2230daca..d7e93335f47fa 100644 --- a/src/test/ui/type-alias-impl-trait/fallback.rs +++ b/src/test/ui/type-alias-impl-trait/fallback.rs @@ -1,5 +1,5 @@ -// Tests that we correctly handle the instantiated -// inference variable being completely unconstrained. +// Tests that we correctly handle opaque types being used opaquely, +// even within their defining scope. // // check-pass #![feature(type_alias_impl_trait)] From 5a374dc813c8c6a1d10b3c6cc7fdeaa9aafbcc65 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Jan 2022 17:20:48 +0000 Subject: [PATCH 18/53] Add some tests to show what happens when you compare two opaque types that are both within the defining scope --- .../two_tait_defining_each_other.rs | 20 +++++++++++++++++++ .../two_tait_defining_each_other2.rs | 16 +++++++++++++++ .../two_tait_defining_each_other2.stderr | 8 ++++++++ .../two_tait_defining_each_other3.rs | 20 +++++++++++++++++++ 4 files changed, 64 insertions(+) create mode 100644 src/test/ui/impl-trait/two_tait_defining_each_other.rs create mode 100644 src/test/ui/impl-trait/two_tait_defining_each_other2.rs create mode 100644 src/test/ui/impl-trait/two_tait_defining_each_other2.stderr create mode 100644 src/test/ui/impl-trait/two_tait_defining_each_other3.rs diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other.rs b/src/test/ui/impl-trait/two_tait_defining_each_other.rs new file mode 100644 index 0000000000000..eb8d24832eb43 --- /dev/null +++ b/src/test/ui/impl-trait/two_tait_defining_each_other.rs @@ -0,0 +1,20 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +type A = impl Foo; +type B = impl Foo; + +trait Foo {} + +fn muh(x: A) -> B { + if false { + return Bar; // B's hidden type is Bar + } + x // A's hidden type is `Bar`, because all the hidden types of `B` are compared with each other +} + +struct Bar; +impl Foo for Bar {} + +fn main() {} diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other2.rs b/src/test/ui/impl-trait/two_tait_defining_each_other2.rs new file mode 100644 index 0000000000000..88a76089b82d1 --- /dev/null +++ b/src/test/ui/impl-trait/two_tait_defining_each_other2.rs @@ -0,0 +1,16 @@ +#![feature(type_alias_impl_trait)] + +type A = impl Foo; +//~^ ERROR could not find defining uses +type B = impl Foo; + +trait Foo {} + +fn muh(x: A) -> B { + x // B's hidden type is A (opaquely) +} + +struct Bar; +impl Foo for Bar {} + +fn main() {} diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other2.stderr b/src/test/ui/impl-trait/two_tait_defining_each_other2.stderr new file mode 100644 index 0000000000000..5a0cff527b6e9 --- /dev/null +++ b/src/test/ui/impl-trait/two_tait_defining_each_other2.stderr @@ -0,0 +1,8 @@ +error: could not find defining uses + --> $DIR/two_tait_defining_each_other2.rs:3:10 + | +LL | type A = impl Foo; + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other3.rs b/src/test/ui/impl-trait/two_tait_defining_each_other3.rs new file mode 100644 index 0000000000000..c289b43c4259f --- /dev/null +++ b/src/test/ui/impl-trait/two_tait_defining_each_other3.rs @@ -0,0 +1,20 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +type A = impl Foo; +type B = impl Foo; + +trait Foo {} + +fn muh(x: A) -> B { + if false { + return x; // B's hidden type is A (opaquely) + } + Bar // A's hidden type is `Bar`, because all the return types are compared with each other +} + +struct Bar; +impl Foo for Bar {} + +fn main() {} From 3146c961fe3c11271313c227aecc610db90a8555 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Jan 2022 14:14:46 +0000 Subject: [PATCH 19/53] We're equating hidden types eagerly now --- compiler/rustc_borrowck/src/type_check/mod.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 6559ded5816d2..eb9d16e01dde8 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -262,10 +262,6 @@ pub(crate) fn type_check<'mir, 'tcx>( } }) .collect(); - // `hidden_type` may re-register an opaque type, so we need to clean out the - // newly re-added types. Either we got here successfully, so they are irrelevant, - // or we already errored anyway. - let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); opaque_type_values }, ); From 94d6a9acc91b9eab01e0815d0683cf2764a543ff Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Jan 2022 14:19:54 +0000 Subject: [PATCH 20/53] This can't happen anymore. An opaque type can't end up with itself as its hidden type --- compiler/rustc_borrowck/src/type_check/mod.rs | 41 ++----------------- 1 file changed, 4 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index eb9d16e01dde8..900ee2455ef0f 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -193,9 +193,9 @@ pub(crate) fn type_check<'mir, 'tcx>( let opaque_type_values = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); - let opaque_type_values = opaque_type_values + opaque_type_values .into_iter() - .filter_map(|(opaque_type_key, decl)| { + .map(|(opaque_type_key, decl)| { cx.fully_perform_op( Locations::All(body.span), ConstraintCategory::OpaqueType, @@ -226,43 +226,10 @@ pub(crate) fn type_check<'mir, 'tcx>( ); hidden_type = infcx.tcx.ty_error(); } - let concrete_is_opaque = if let ty::Opaque(def_id, _) = hidden_type.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, (hidden_type, decl.hidden_type.span, decl.origin))) - } + (opaque_type_key, (hidden_type, decl.hidden_type.span, decl.origin)) }) - .collect(); - opaque_type_values + .collect() }, ); From 22477784a72ab1e5b26f8cb555f02e691d066898 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Jan 2022 14:27:38 +0000 Subject: [PATCH 21/53] Fixup changes that aren't neccessary anymore --- compiler/rustc_borrowck/src/type_check/mod.rs | 5 ----- .../rustc_const_eval/src/transform/check_consts/check.rs | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 900ee2455ef0f..4647610b0033d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1745,11 +1745,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { fn ensure_place_sized(&mut self, ty: Ty<'tcx>, span: Span) { let tcx = self.tcx(); - // This may contain opaque types, resolve them to the underlying - // type if defined in the current function. Otherwise we can't - // necessarily prove sizedness of the type. - let ty = self.infcx.resolve_vars_if_possible(ty); - // Erase the regions from `ty` to get a global type. The // `Sized` bound in no way depends on precise regions, so this // shouldn't affect `is_sized`. diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index e2dbeef35b9d3..49a9b911f3a4b 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -48,7 +48,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { let ty = ccx.body.local_decls[local].ty; // Peeking into opaque types causes cycles if the current function declares said opaque // type. Thus we avoid short circuiting on the type and instead run the more expensive - // analysis that looks at the actual usage withhin this function + // analysis that looks at the actual usage within this function if !ty.has_opaque_types() && !NeedsDrop::in_any_value_of_ty(ccx, ty) { return false; } @@ -105,7 +105,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { let ty = ccx.body.local_decls[local].ty; // Peeking into opaque types causes cycles if the current function declares said opaque // type. Thus we avoid short circuiting on the type and instead run the more expensive - // analysis that looks at the actual usage withhin this function + // analysis that looks at the actual usage within this function if !ty.has_opaque_types() && !HasMutInterior::in_any_value_of_ty(ccx, ty) { return false; } From e03edd287e774e737add22fd957e1cf4c813e1ea Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Jan 2022 14:31:24 +0000 Subject: [PATCH 22/53] Inline a function that is only ever used in one place --- .../rustc_infer/src/infer/opaque_types.rs | 70 +------------------ 1 file changed, 2 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 748fe1379cd62..b455e7f149dbc 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -71,43 +71,6 @@ pub struct OpaqueHiddenType<'tcx> { } impl<'a, 'tcx> InferCtxt<'a, 'tcx> { - /// Links the opaque type with the given hidden type - /// and creates appropriate obligations. For example, given the input: - /// - /// opaque = impl Iterator - /// hidden = std::vec::IntoIter - /// - /// this method would register the opaque type `impl Iterator` to have - /// the hidden type `std::vec::IntoIter` and create the type variable - /// `?1` but also the obligations: - /// - /// std::vec::IntoIter: Iterator - /// ?1: Debug - /// - /// Moreover, it returns an `OpaqueTypeMap` that would map `?0` to - /// info about the `impl Iterator<..>` type and `?1` to info about - /// the `impl Debug` type. - /// - /// # Parameters - /// - /// - `parent_def_id` -- the `DefId` of the function in which the opaque type - /// is defined - /// - `body_id` -- the body-id with which the resulting obligations should - /// be associated - /// - `param_env` -- the in-scope parameter environment to be used for - /// obligations - /// - `value` -- the value within which we are instantiating opaque types - /// - `value_span` -- the span where the value came from, used in error reporting - pub fn instantiate_opaque_types( - &self, - ty: Ty<'tcx>, - opaque: Ty<'tcx>, - cause: ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ) -> Option> { - Instantiator { infcx: self, cause, param_env }.fold_opaque_ty_new(opaque, |_, _| ty) - } - pub fn handle_opaque_type( &self, a: Ty<'tcx>, @@ -123,7 +86,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if !matches!(a.kind(), ty::Opaque(..)) { return None; } - self.instantiate_opaque_types(b, a, cause.clone(), param_env) + Instantiator { infcx: self, cause: cause.clone(), param_env } + .fold_opaque_ty_new(a, |_, _| b) }; if let Some(res) = process(a, b) { res @@ -298,36 +262,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// but this is not necessary, because the opaque type we /// create will be allowed to reference `T`. So we only generate a /// constraint that `'0: 'a`. - /// - /// # The `free_region_relations` parameter - /// - /// The `free_region_relations` argument is used to find the - /// "minimum" of the regions supplied to a given opaque type. - /// It must be a relation that can answer whether `'a <= 'b`, - /// where `'a` and `'b` are regions that appear in the "substs" - /// for the opaque type references (the `<'a>` in `Foo1<'a>`). - /// - /// Note that we do not impose the constraints based on the - /// generic regions from the `Foo1` definition (e.g., `'x`). This - /// is because the constraints we are imposing here is basically - /// the concern of the one generating the constraining type C1, - /// which is the current function. It also means that we can - /// take "implied bounds" into account in some cases: - /// - /// ```text - /// trait SomeTrait<'a, 'b> { } - /// fn foo<'a, 'b>(_: &'a &'b u32) -> impl SomeTrait<'a, 'b> { .. } - /// ``` - /// - /// Here, the fact that `'b: 'a` is known only because of the - /// implied bounds from the `&'a &'b u32` parameter, and is not - /// "inherent" to the opaque type definition. - /// - /// # Parameters - /// - /// - `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. #[instrument(level = "debug", skip(self))] pub fn register_member_constraints( &self, From fcba8d31c44f6c18121e3d37311b0797bbeb033f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Jan 2022 14:41:28 +0000 Subject: [PATCH 23/53] Remove the `Instantiator` now that we don't recurse within it anymore --- .../rustc_infer/src/infer/opaque_types.rs | 47 ++++++++----------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index b455e7f149dbc..4ac070a95e54c 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -86,8 +86,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if !matches!(a.kind(), ty::Opaque(..)) { return None; } - Instantiator { infcx: self, cause: cause.clone(), param_env } - .fold_opaque_ty_new(a, |_, _| b) + self.fold_opaque_ty_new(a, cause.clone(), param_env, |_, _| b) }; if let Some(res) = process(a, b) { res @@ -480,16 +479,12 @@ impl UseKind { } } -struct Instantiator<'a, 'tcx> { - infcx: &'a InferCtxt<'a, 'tcx>, - cause: ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, -} - -impl<'a, 'tcx> Instantiator<'a, 'tcx> { +impl<'a, 'tcx> InferCtxt<'a, 'tcx> { fn fold_opaque_ty_new( - &mut self, + &self, ty: Ty<'tcx>, + cause: ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, mk_ty: impl FnOnce(&InferCtxt<'_, 'tcx>, Span) -> Ty<'tcx>, ) -> Option> { // Check that this is `impl Trait` type is @@ -527,9 +522,8 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { // } // ``` let opaque_type_key = ty.expect_opaque_type(); - if let Some(origin) = self.infcx.opaque_type_origin(opaque_type_key.def_id, self.cause.span) - { - return Some(self.fold_opaque_ty(ty, opaque_type_key, origin, mk_ty)); + if let Some(origin) = self.opaque_type_origin(opaque_type_key.def_id, cause.span) { + return Some(self.fold_opaque_ty(ty, cause, param_env, opaque_type_key, origin, mk_ty)); } debug!(?ty, "encountered opaque outside its definition scope",); @@ -538,34 +532,35 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { #[instrument(skip(self, mk_ty), level = "debug")] fn fold_opaque_ty( - &mut self, + &self, ty: Ty<'tcx>, + cause: ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, opaque_type_key: OpaqueTypeKey<'tcx>, origin: hir::OpaqueTyOrigin, mk_ty: impl FnOnce(&InferCtxt<'_, 'tcx>, Span) -> Ty<'tcx>, ) -> InferResult<'tcx, ()> { - let infcx = self.infcx; - let tcx = infcx.tcx; + let tcx = self.tcx; let OpaqueTypeKey { def_id, substs } = opaque_type_key; - let ty_var = mk_ty(infcx, self.cause.span); + let ty_var = mk_ty(self, cause.span); // Ideally, we'd get the span where *this specific `ty` came // from*, but right now we just use the span from the overall // value being folded. In simple cases like `-> impl Foo`, // these are the same span, but not in cases like `-> (impl // Foo, impl Bar)`. - let span = self.cause.span; + let span = cause.span; let mut obligations = vec![]; - let prev = self.infcx.inner.borrow_mut().opaque_types().register( + let prev = self.inner.borrow_mut().opaque_types().register( OpaqueTypeKey { def_id, substs }, ty, OpaqueHiddenType { ty: ty_var, span }, origin, ); if let Some(prev) = prev { - obligations = self.infcx.at(&self.cause, self.param_env).eq(prev, ty_var)?.obligations; + obligations = self.at(&cause, param_env).eq(prev, ty_var)?.obligations; } debug!("generated new type inference var {:?}", ty_var.kind()); @@ -581,10 +576,10 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { ty_op: |ty| match *ty.kind() { // We can't normalize associated types from `rustc_infer`, // but we can eagerly register inference variables for them. - ty::Projection(projection_ty) if !projection_ty.has_escaping_bound_vars() => infcx.infer_projection( - self.param_env, + ty::Projection(projection_ty) if !projection_ty.has_escaping_bound_vars() => self.infer_projection( + param_env, projection_ty, - self.cause.clone(), + cause.clone(), 0, &mut obligations, ), @@ -608,11 +603,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { } // Require that the predicate holds for the concrete type. debug!(?predicate); - obligations.push(traits::Obligation::new( - self.cause.clone(), - self.param_env, - predicate, - )); + obligations.push(traits::Obligation::new(cause.clone(), param_env, predicate)); } Ok(InferOk { value: (), obligations }) } From 5b49b8e2d52f421c45349214bc805710e6ba5da4 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Jan 2022 14:45:15 +0000 Subject: [PATCH 24/53] Remove unnecessary closure in favour of just passing the argument directly --- .../rustc_infer/src/infer/opaque_types.rs | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 4ac070a95e54c..2e3c860548607 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -86,7 +86,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if !matches!(a.kind(), ty::Opaque(..)) { return None; } - self.fold_opaque_ty_new(a, cause.clone(), param_env, |_, _| b) + self.fold_opaque_ty_new(a, cause.clone(), param_env, b) }; if let Some(res) = process(a, b) { res @@ -482,10 +482,10 @@ impl UseKind { impl<'a, 'tcx> InferCtxt<'a, 'tcx> { fn fold_opaque_ty_new( &self, - ty: Ty<'tcx>, + opaque_type: Ty<'tcx>, cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, - mk_ty: impl FnOnce(&InferCtxt<'_, 'tcx>, Span) -> Ty<'tcx>, + hidden_ty: Ty<'tcx>, ) -> Option> { // Check that this is `impl Trait` type is // declared by `parent_def_id` -- i.e., one whose @@ -521,30 +521,35 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // let x = || foo(); // returns the Opaque assoc with `foo` // } // ``` - let opaque_type_key = ty.expect_opaque_type(); + let opaque_type_key = opaque_type.expect_opaque_type(); if let Some(origin) = self.opaque_type_origin(opaque_type_key.def_id, cause.span) { - return Some(self.fold_opaque_ty(ty, cause, param_env, opaque_type_key, origin, mk_ty)); + return Some(self.fold_opaque_ty( + opaque_type, + cause, + param_env, + opaque_type_key, + origin, + hidden_ty, + )); } - debug!(?ty, "encountered opaque outside its definition scope",); + debug!(?opaque_type, "encountered opaque outside its definition scope",); None } - #[instrument(skip(self, mk_ty), level = "debug")] + #[instrument(skip(self), level = "debug")] fn fold_opaque_ty( &self, - ty: Ty<'tcx>, + opaque_type: Ty<'tcx>, cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, opaque_type_key: OpaqueTypeKey<'tcx>, origin: hir::OpaqueTyOrigin, - mk_ty: impl FnOnce(&InferCtxt<'_, 'tcx>, Span) -> Ty<'tcx>, + hidden_ty: Ty<'tcx>, ) -> InferResult<'tcx, ()> { let tcx = self.tcx; let OpaqueTypeKey { def_id, substs } = opaque_type_key; - let ty_var = mk_ty(self, cause.span); - // Ideally, we'd get the span where *this specific `ty` came // from*, but right now we just use the span from the overall // value being folded. In simple cases like `-> impl Foo`, @@ -555,16 +560,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let mut obligations = vec![]; let prev = self.inner.borrow_mut().opaque_types().register( OpaqueTypeKey { def_id, substs }, - ty, - OpaqueHiddenType { ty: ty_var, span }, + opaque_type, + OpaqueHiddenType { ty: hidden_ty, span }, origin, ); if let Some(prev) = prev { - obligations = self.at(&cause, param_env).eq(prev, ty_var)?.obligations; + obligations = self.at(&cause, param_env).eq(prev, hidden_ty)?.obligations; } - debug!("generated new type inference var {:?}", ty_var.kind()); - let item_bounds = tcx.explicit_item_bounds(def_id); for (predicate, _) in item_bounds { @@ -586,7 +589,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // Replace all other mentions of the same opaque type with the hidden type, // as the bounds must hold on the hidden type after all. ty::Opaque(def_id2, substs2) if def_id == def_id2 && substs == substs2 => { - ty_var + hidden_ty } _ => ty, }, From d35d1ef4f52a6e90e138c3c4bd7cd23a044ae6e4 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Jan 2022 14:52:24 +0000 Subject: [PATCH 25/53] Remove unnecessary field --- .../rustc_infer/src/infer/opaque_types.rs | 33 +++++++------------ .../src/infer/opaque_types/table.rs | 3 +- 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 2e3c860548607..7231bc70904f2 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -26,9 +26,6 @@ use super::InferResult; /// appear in the return type). #[derive(Clone, Debug)] pub struct OpaqueTypeDecl<'tcx> { - /// The opaque type (`ty::Opaque`) for this declaration. - pub opaque_type: Ty<'tcx>, - /// The hidden types that have been inferred for this opaque type. /// There can be multiple, but they are all `lub`ed together at the end /// to obtain the canonical hidden type. @@ -82,11 +79,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { return Ok(InferOk { value: (), obligations: vec![] }); } if self.defining_use_anchor.is_some() { - let process = |a: Ty<'tcx>, b: Ty<'tcx>| { - if !matches!(a.kind(), ty::Opaque(..)) { - return None; - } - self.fold_opaque_ty_new(a, cause.clone(), param_env, b) + let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() { + ty::Opaque(def_id, substs) => self.fold_opaque_ty_new( + OpaqueTypeKey { def_id, substs }, + cause.clone(), + param_env, + b, + ), + _ => None, }; if let Some(res) = process(a, b) { res @@ -118,7 +118,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let origin = self.opaque_ty_origin_unchecked(key.def_id, cause.span); let prev = self.inner.borrow_mut().opaque_types().register( key, - opaque_type, OpaqueHiddenType { ty: hidden_ty, span: cause.span }, origin, ); @@ -482,7 +481,7 @@ impl UseKind { impl<'a, 'tcx> InferCtxt<'a, 'tcx> { fn fold_opaque_ty_new( &self, - opaque_type: Ty<'tcx>, + opaque_type_key: OpaqueTypeKey<'tcx>, cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, hidden_ty: Ty<'tcx>, @@ -521,26 +520,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // let x = || foo(); // returns the Opaque assoc with `foo` // } // ``` - let opaque_type_key = opaque_type.expect_opaque_type(); if let Some(origin) = self.opaque_type_origin(opaque_type_key.def_id, cause.span) { - return Some(self.fold_opaque_ty( - opaque_type, - cause, - param_env, - opaque_type_key, - origin, - hidden_ty, - )); + return Some(self.fold_opaque_ty(cause, param_env, opaque_type_key, origin, hidden_ty)); } - debug!(?opaque_type, "encountered opaque outside its definition scope",); + debug!(?opaque_type_key, "encountered opaque outside its definition scope",); None } #[instrument(skip(self), level = "debug")] fn fold_opaque_ty( &self, - opaque_type: Ty<'tcx>, cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, opaque_type_key: OpaqueTypeKey<'tcx>, @@ -560,7 +550,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let mut obligations = vec![]; let prev = self.inner.borrow_mut().opaque_types().register( OpaqueTypeKey { def_id, substs }, - opaque_type, OpaqueHiddenType { ty: hidden_ty, span }, origin, ); diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs index 7f16a2f533226..9b8f225ce367b 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/table.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -72,7 +72,6 @@ impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> { pub fn register( &mut self, key: OpaqueTypeKey<'tcx>, - opaque_type: Ty<'tcx>, hidden_type: OpaqueHiddenType<'tcx>, origin: OpaqueTyOrigin, ) -> Option> { @@ -81,7 +80,7 @@ impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> { self.undo_log.push(UndoLog::OpaqueTypes(key, Some(prev))); return Some(prev.ty); } - let decl = OpaqueTypeDecl { opaque_type, hidden_type, origin }; + let decl = OpaqueTypeDecl { hidden_type, origin }; self.storage.opaque_types.insert(key, decl); self.undo_log.push(UndoLog::OpaqueTypes(key, None)); None From b45fabddfddd3d70d79848be5ff45dd5ef6de9c5 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Jan 2022 14:57:56 +0000 Subject: [PATCH 26/53] Inline a function that is only used once --- .../rustc_infer/src/infer/opaque_types.rs | 92 ++++++++----------- 1 file changed, 39 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 7231bc70904f2..0819c2363ffbc 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -80,12 +80,47 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } if self.defining_use_anchor.is_some() { let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() { - ty::Opaque(def_id, substs) => self.fold_opaque_ty_new( + ty::Opaque(def_id, substs) => Some(self.register_hidden_type( OpaqueTypeKey { def_id, substs }, cause.clone(), param_env, b, - ), + // Check that this is `impl Trait` type is + // declared by `parent_def_id` -- i.e., one whose + // value we are inferring. At present, this is + // always true during the first phase of + // type-check, but not always true later on during + // NLL. Once we support named opaque types more fully, + // this same scenario will be able to arise during all phases. + // + // Here is an example using type alias `impl Trait` + // that indicates the distinction we are checking for: + // + // ```rust + // mod a { + // pub type Foo = impl Iterator; + // pub fn make_foo() -> Foo { .. } + // } + // + // mod b { + // fn foo() -> a::Foo { a::make_foo() } + // } + // ``` + // + // Here, the return type of `foo` references an + // `Opaque` indeed, but not one whose value is + // presently being inferred. You can get into a + // similar situation with closure return types + // today: + // + // ```rust + // fn foo() -> impl Iterator { .. } + // fn bar() { + // let x = || foo(); // returns the Opaque assoc with `foo` + // } + // ``` + self.opaque_type_origin(def_id, cause.span)?, + )), _ => None, }; if let Some(res) = process(a, b) { @@ -479,63 +514,14 @@ impl UseKind { } impl<'a, 'tcx> InferCtxt<'a, 'tcx> { - fn fold_opaque_ty_new( + #[instrument(skip(self), level = "debug")] + fn register_hidden_type( &self, opaque_type_key: OpaqueTypeKey<'tcx>, cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, hidden_ty: Ty<'tcx>, - ) -> Option> { - // Check that this is `impl Trait` type is - // declared by `parent_def_id` -- i.e., one whose - // value we are inferring. At present, this is - // always true during the first phase of - // type-check, but not always true later on during - // NLL. Once we support named opaque types more fully, - // this same scenario will be able to arise during all phases. - // - // Here is an example using type alias `impl Trait` - // that indicates the distinction we are checking for: - // - // ```rust - // mod a { - // pub type Foo = impl Iterator; - // pub fn make_foo() -> Foo { .. } - // } - // - // mod b { - // fn foo() -> a::Foo { a::make_foo() } - // } - // ``` - // - // Here, the return type of `foo` references an - // `Opaque` indeed, but not one whose value is - // presently being inferred. You can get into a - // similar situation with closure return types - // today: - // - // ```rust - // fn foo() -> impl Iterator { .. } - // fn bar() { - // let x = || foo(); // returns the Opaque assoc with `foo` - // } - // ``` - if let Some(origin) = self.opaque_type_origin(opaque_type_key.def_id, cause.span) { - return Some(self.fold_opaque_ty(cause, param_env, opaque_type_key, origin, hidden_ty)); - } - - debug!(?opaque_type_key, "encountered opaque outside its definition scope",); - None - } - - #[instrument(skip(self), level = "debug")] - fn fold_opaque_ty( - &self, - cause: ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - opaque_type_key: OpaqueTypeKey<'tcx>, origin: hir::OpaqueTyOrigin, - hidden_ty: Ty<'tcx>, ) -> InferResult<'tcx, ()> { let tcx = self.tcx; let OpaqueTypeKey { def_id, substs } = opaque_type_key; From dbda6754194bbfd34980916a62acd01baf5e75e4 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Jan 2022 15:05:50 +0000 Subject: [PATCH 27/53] Undo a diff --- compiler/rustc_infer/src/infer/freshen.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index d159c14b1cfb7..4af1bdf97a773 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -214,8 +214,8 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { | ty::Foreign(..) | ty::Param(..) | ty::Closure(..) - | ty::Opaque(..) - | ty::GeneratorWitness(..) => t.super_fold_with(self), + | ty::GeneratorWitness(..) + | ty::Opaque(..) => t.super_fold_with(self), ty::Placeholder(..) | ty::Bound(..) => bug!("unexpected type {:?}", t), } From d8c29b3e28b3f22a3ec6e8efc416b53cc044a882 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Jan 2022 15:06:33 +0000 Subject: [PATCH 28/53] Simplify diff --- compiler/rustc_infer/src/infer/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 15ce690479b1a..fa17a2d66f117 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -190,10 +190,10 @@ pub struct InferCtxtInner<'tcx> { /// that all type inference variables have been bound and so forth. region_obligations: Vec<(hir::HirId, RegionObligation<'tcx>)>, + undo_log: InferCtxtUndoLogs<'tcx>, + /// Caches for opaque type inference. pub opaque_type_storage: OpaqueTypeStorage<'tcx>, - - undo_log: InferCtxtUndoLogs<'tcx>, } impl<'tcx> InferCtxtInner<'tcx> { From d3b534b6b5c61246d8fd97dad9c1b7e9c8fbe3c1 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Jan 2022 15:09:39 +0000 Subject: [PATCH 29/53] manual formatting --- compiler/rustc_lint/src/builtin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 442e756715b77..44e3da11826cd 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1654,7 +1654,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { Coerce(..) | ConstEvaluatable(..) | ConstEquate(..) | - OpaqueType(..) | + OpaqueType(..) | TypeWellFormedFromEnv(..) => continue, }; if predicate.is_global() { From dc36b385261a8200f8259feddef58715549f2563 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Jan 2022 15:15:30 +0000 Subject: [PATCH 30/53] Make a comment more obvious --- compiler/rustc_trait_selection/src/traits/select/mod.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 35818786cbbf1..a183a20a2fed0 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2248,8 +2248,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result>, ()> { self.infcx .at(&obligation.cause, obligation.param_env) - // We don't want opaque types to just randomly match everything, - // they should be opaque, even in their defining scope. + // We don't want predicates for opaque types to just match all other types, + // if there is an obligation on the opaque type, then that obligation must be met + // opaquely. Otherwise we'd match any obligation to the opaque type and then error + // out later. .define_opaque_types(false) .sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref) .map(|InferOk { obligations, .. }| obligations) From 3d4b9b8b8bd3ea9c29f9cfefa686da785044ae9a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Jan 2022 15:33:15 +0000 Subject: [PATCH 31/53] Remove some unused arguments and update a comment --- compiler/rustc_type_ir/src/lib.rs | 6 ++++-- compiler/rustc_typeck/src/check/_match.rs | 6 ++---- compiler/rustc_typeck/src/check/expr.rs | 3 +-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 94476ee2c4101..741438b3d29cc 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -61,8 +61,10 @@ bitflags! { | TypeFlags::HAS_CT_INFER.bits | TypeFlags::HAS_TY_PLACEHOLDER.bits | TypeFlags::HAS_CT_PLACEHOLDER.bits - // Opaque types may get resolved in the current scope and must - // thus not be transported to other queries if it can be avoided. + // The `evaluate_obligation` query does not return further + // obligations. If it evaluates an obligation with an opaque + // type, that opaque type may get compared to another type, + // constraining it. We would lose this information. // FIXME: differentiate between crate-local opaque types // and opaque types from other crates, as only opaque types // from the local crate can possibly be a local name diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index bc5662b596093..75e461454543e 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -98,8 +98,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let arm_ty = self.check_expr_with_expectation(&arm.body, expected); all_arms_diverge &= self.diverges.get(); - let opt_suggest_box_span = - self.opt_suggest_box_span(arm.body.span, arm_ty, orig_expected); + let opt_suggest_box_span = self.opt_suggest_box_span(arm_ty, orig_expected); let (arm_span, semi_span) = self.get_appropriate_arm_semicolon_removal_span(&arms, i, prior_arm_ty, arm_ty); @@ -504,12 +503,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // provide a structured suggestion in that case. pub(crate) fn opt_suggest_box_span( &self, - _span: Span, outer_ty: &'tcx TyS<'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(_)) if self.in_tail_expr && self.can_coerce(outer_ty, expected) => { let obligations = self.fulfillment_cx.borrow().pending_obligations(); diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 0e1dbc53806ff..d9b63152e3fe7 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -948,8 +948,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let else_diverges = self.diverges.get(); - let opt_suggest_box_span = - self.opt_suggest_box_span(else_expr.span, else_ty, orig_expected); + let opt_suggest_box_span = self.opt_suggest_box_span(else_ty, orig_expected); let if_cause = self.if_cause(sp, then_expr, else_expr, then_ty, else_ty, opt_suggest_box_span); From c5648981108e50cf706d146ad9e1b35742102a27 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Jan 2022 15:46:48 +0000 Subject: [PATCH 32/53] Remove a now-useless field --- compiler/rustc_typeck/src/check/_match.rs | 10 ++++++---- compiler/rustc_typeck/src/check/check.rs | 5 ----- compiler/rustc_typeck/src/check/fn_ctxt/mod.rs | 3 --- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index 75e461454543e..195fbd7752065 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -4,7 +4,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir::{self as hir, ExprKind}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::traits::Obligation; -use rustc_middle::ty::{self, ToPredicate, Ty, TyS}; +use rustc_middle::ty::{self, ToPredicate, Ty, TyS, TypeFoldable}; use rustc_span::{MultiSpan, Span}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{ @@ -506,9 +506,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { outer_ty: &'tcx TyS<'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(_)) - if self.in_tail_expr && self.can_coerce(outer_ty, expected) => + match orig_expected { + Expectation::ExpectHasType(expected) + if self.in_tail_expr + && self.ret_coercion.as_ref()?.borrow().merged_ty().has_opaque_types() + && self.can_coerce(outer_ty, expected) => { let obligations = self.fulfillment_cx.borrow().pending_obligations(); let mut suggest_box = !obligations.is_empty(); diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 3405619f403b2..d10d3e43b5b18 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -95,11 +95,6 @@ pub(super) fn check_fn<'a, 'tcx>( fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(declared_ret_ty))); fcx.ret_type_span = Some(decl.output.span()); - if let ty::Opaque(..) = declared_ret_ty.kind() { - // FIXME(oli-obk): remove this and have diagnostics check the signature's return type directly - // as we don't reveal here anymore. - fcx.ret_coercion_impl_trait = Some(declared_ret_ty); - } let span = body.value.span; diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs index 3a81af0316286..234775ab45269 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs @@ -57,8 +57,6 @@ pub struct FnCtxt<'a, 'tcx> { /// any). pub(super) ret_coercion: Option>>, - pub(super) ret_coercion_impl_trait: Option>, - pub(super) ret_type_span: Option, /// Used exclusively to reduce cost of advanced evaluation used for @@ -130,7 +128,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { param_env, err_count_on_creation: inh.tcx.sess.err_count(), ret_coercion: None, - ret_coercion_impl_trait: None, ret_type_span: None, in_tail_expr: false, ret_coercion_span: Cell::new(None), From e4794d9d1b8d2ad206ce0aca2afe91d38c6d3420 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Jan 2022 15:46:59 +0000 Subject: [PATCH 33/53] Undo a change that is now unnecessary --- compiler/rustc_typeck/src/check/fallback.rs | 2 +- compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs | 2 +- compiler/rustc_typeck/src/check/inherited.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_typeck/src/check/fallback.rs b/compiler/rustc_typeck/src/check/fallback.rs index bbe34977c911a..8513231782407 100644 --- a/compiler/rustc_typeck/src/check/fallback.rs +++ b/compiler/rustc_typeck/src/check/fallback.rs @@ -218,7 +218,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { .diverging_type_vars .borrow() .iter() - .map(|(&ty, _)| self.infcx.shallow_resolve(ty)) + .map(|&ty| self.infcx.shallow_resolve(ty)) .filter_map(|ty| ty.ty_vid()) .map(|vid| self.infcx.root_var(vid)) .collect(); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 705b3207999a7..e60893a658b3d 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -274,7 +274,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for a in &adj { if let Adjust::NeverToAny = a.kind { if a.target.is_ty_var() { - self.diverging_type_vars.borrow_mut().insert(a.target, expr.span); + self.diverging_type_vars.borrow_mut().insert(a.target); debug!("apply_adjustments: adding `{:?}` as diverging type var", a.target); } } diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs index c9b843aedb2d4..b775f24f8efd8 100644 --- a/compiler/rustc_typeck/src/check/inherited.rs +++ b/compiler/rustc_typeck/src/check/inherited.rs @@ -1,7 +1,7 @@ use super::callee::DeferredCallResolution; use super::MaybeInProgressTables; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::{DefIdMap, LocalDefId}; use rustc_hir::HirIdMap; @@ -58,7 +58,7 @@ pub struct Inherited<'a, 'tcx> { /// Whenever we introduce an adjustment from `!` into a type variable, /// we record that type variable here. This is later used to inform /// fallback. See the `fallback` module for details. - pub(super) diverging_type_vars: RefCell, Span>>, + pub(super) diverging_type_vars: RefCell>>, } impl<'a, 'tcx> Deref for Inherited<'a, 'tcx> { From b6d57ecc0bdbb3b6c3848782129703dd4cb251eb Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Jan 2022 16:11:28 +0000 Subject: [PATCH 34/53] Hide further opaque type errors if items that could constrain the opaque type have errors --- compiler/rustc_typeck/src/collect/type_of.rs | 7 ++++++- .../assoc-type-eq-with-dyn-atb-fail.rs | 1 - .../assoc-type-eq-with-dyn-atb-fail.stderr | 10 ++-------- src/test/ui/impl-trait/issue-55872-1.rs | 1 - src/test/ui/impl-trait/issue-55872-1.stderr | 14 ++++---------- src/test/ui/impl-trait/issue-55872-3.rs | 1 - src/test/ui/impl-trait/issue-55872-3.stderr | 10 ++-------- ...c_type_does_not_live_long_enough.nll.stderr | 2 +- .../generic_type_does_not_live_long_enough.rs | 1 - ...neric_type_does_not_live_long_enough.stderr | 10 ++-------- .../type-alias-impl-trait/inference-cycle.rs | 2 +- .../inference-cycle.stderr | 14 +------------- .../issue-57611-trait-alias.nll.stderr | 6 +++--- .../issue-57611-trait-alias.rs | 1 - .../issue-57611-trait-alias.stderr | 10 ++-------- .../ui/type-alias-impl-trait/issue-60371.rs | 1 - .../type-alias-impl-trait/issue-60371.stderr | 10 ++-------- .../ui/type-alias-impl-trait/issue-63279.rs | 1 - .../type-alias-impl-trait/issue-63279.stderr | 18 ++++++------------ .../ui/type-alias-impl-trait/issue-74280.rs | 1 - .../type-alias-impl-trait/issue-74280.stderr | 10 ++-------- .../multiple-def-uses-in-one-fn.rs | 1 - .../multiple-def-uses-in-one-fn.stderr | 10 ++-------- .../nested-tait-inference.rs | 1 - .../nested-tait-inference.stderr | 10 ++-------- .../nested-tait-inference2.rs | 1 - .../nested-tait-inference2.stderr | 10 ++-------- 27 files changed, 40 insertions(+), 124 deletions(-) diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 4b61e21c0e0cf..67a8ae4c1f778 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -607,7 +607,12 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { // // because we again need to reveal `Foo` so we can check whether the // // constant does not contain interior mutability. // ``` - if self.tcx.typeck(def_id).concrete_opaque_types.get(&self.def_id).is_none() { + let tables = self.tcx.typeck(def_id); + if let Some(_) = tables.tainted_by_errors { + self.found = Some((DUMMY_SP, self.tcx.ty_error())); + return; + } + if tables.concrete_opaque_types.get(&self.def_id).is_none() { debug!("no constraints in typeck results"); return; } 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 ac3df7fca5ab2..67b97c21805e6 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,7 +28,6 @@ impl Bar for AssocNoCopy { impl Thing for AssocNoCopy { type Out = Box>; - //~^ ERROR could not find defining uses fn func() -> Self::Out { 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 3cbc3358d07fb..be4bfa6272b8d 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,17 +1,11 @@ error[E0277]: the trait bound `String: Copy` is not satisfied - --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:34:9 + --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:33:9 | LL | Box::new(AssocNoCopy) | ^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` | = note: required for the cast to the object type `dyn Bar` -error: could not find defining uses - --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:30:28 - | -LL | type Out = Box>; - | ^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/issue-55872-1.rs b/src/test/ui/impl-trait/issue-55872-1.rs index 7d29882995355..a75b9b43b3e8b 100644 --- a/src/test/ui/impl-trait/issue-55872-1.rs +++ b/src/test/ui/impl-trait/issue-55872-1.rs @@ -8,7 +8,6 @@ pub trait Bar { impl Bar for S { type E = impl Copy; - //~^ ERROR could not find defining uses fn foo() -> Self::E { //~^ ERROR impl has stricter requirements than trait diff --git a/src/test/ui/impl-trait/issue-55872-1.stderr b/src/test/ui/impl-trait/issue-55872-1.stderr index 95138d86743cc..efc57da746132 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:13:15 + --> $DIR/issue-55872-1.rs:12:15 | LL | fn foo() -> Self::E; | ----------------------- definition of `foo` from trait @@ -8,7 +8,7 @@ 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:15:9 + --> $DIR/issue-55872-1.rs:14:9 | LL | (S::default(), T::default()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S` @@ -20,7 +20,7 @@ LL | impl Bar for S { | +++++++++++++++++++ error[E0277]: the trait bound `T: Copy` is not satisfied in `(S, T)` - --> $DIR/issue-55872-1.rs:15:9 + --> $DIR/issue-55872-1.rs:14:9 | LL | (S::default(), T::default()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T` @@ -31,13 +31,7 @@ help: consider further restricting this bound LL | fn foo() -> Self::E { | +++++++++++++++++++ -error: could not find defining uses - --> $DIR/issue-55872-1.rs:10:14 - | -LL | type E = impl Copy; - | ^^^^^^^^^ - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0276, E0277. For more information about an error, try `rustc --explain E0276`. diff --git a/src/test/ui/impl-trait/issue-55872-3.rs b/src/test/ui/impl-trait/issue-55872-3.rs index 70f3c3c737ac9..f50b31ff496ae 100644 --- a/src/test/ui/impl-trait/issue-55872-3.rs +++ b/src/test/ui/impl-trait/issue-55872-3.rs @@ -11,7 +11,6 @@ pub trait Bar { impl Bar for S { type E = impl std::marker::Copy; - //~^ ERROR could not find defining uses fn foo() -> Self::E { async {} //~^ ERROR the trait bound `impl Future: Copy` is not satisfied [E0277] diff --git a/src/test/ui/impl-trait/issue-55872-3.stderr b/src/test/ui/impl-trait/issue-55872-3.stderr index 5ef0b02006a71..bafd31f0083e8 100644 --- a/src/test/ui/impl-trait/issue-55872-3.stderr +++ b/src/test/ui/impl-trait/issue-55872-3.stderr @@ -1,15 +1,9 @@ error[E0277]: the trait bound `impl Future: Copy` is not satisfied - --> $DIR/issue-55872-3.rs:16:9 + --> $DIR/issue-55872-3.rs:15:9 | LL | async {} | ^^^^^^^^ the trait `Copy` is not implemented for `impl Future` -error: could not find defining uses - --> $DIR/issue-55872-3.rs:13:14 - | -LL | type E = impl std::marker::Copy; - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. 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 8c5659ed12c08..ef9756acee058 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 @@ -17,7 +17,7 @@ LL | type WrongGeneric = impl 'static; | ^ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/generic_type_does_not_live_long_enough.rs:15:5 + --> $DIR/generic_type_does_not_live_long_enough.rs:14:5 | LL | t | ^ 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 4a7d640fe84de..cb90776472b5d 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 @@ -9,7 +9,6 @@ fn main() { type WrongGeneric = impl 'static; //~^ ERROR: at least one trait must be specified -//~| ERROR could not find defining uses fn wrong_generic(t: T) -> WrongGeneric { 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 22f8a757aad1d..15ec2eed3da4b 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 @@ -17,19 +17,13 @@ LL | type WrongGeneric = impl 'static; | ^ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/generic_type_does_not_live_long_enough.rs:15:5 + --> $DIR/generic_type_does_not_live_long_enough.rs:14:5 | LL | fn wrong_generic(t: T) -> WrongGeneric { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | t | ^ ...so that the type `T` will meet its required lifetime bounds -error: could not find defining uses - --> $DIR/generic_type_does_not_live_long_enough.rs:10:24 - | -LL | type WrongGeneric = impl 'static; - | ^^^^^^^^^^^^ - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/type-alias-impl-trait/inference-cycle.rs b/src/test/ui/type-alias-impl-trait/inference-cycle.rs index d00b6ce3f82c5..608572978a351 100644 --- a/src/test/ui/type-alias-impl-trait/inference-cycle.rs +++ b/src/test/ui/type-alias-impl-trait/inference-cycle.rs @@ -16,7 +16,7 @@ mod m { is_send(foo()); // Today: error } - fn baz() { //~ ERROR concrete type differs from previous defining opaque type use + fn baz() { let f: Foo = 22_u32; } diff --git a/src/test/ui/type-alias-impl-trait/inference-cycle.stderr b/src/test/ui/type-alias-impl-trait/inference-cycle.stderr index 90032f589e009..3ed86fae8a18d 100644 --- a/src/test/ui/type-alias-impl-trait/inference-cycle.stderr +++ b/src/test/ui/type-alias-impl-trait/inference-cycle.stderr @@ -34,18 +34,6 @@ note: cycle used when checking item types in module `m` LL | mod m { | ^^^^^ -error: concrete type differs from previous defining opaque type use - --> $DIR/inference-cycle.rs:19:5 - | -LL | fn baz() { - | ^^^^^^^^ expected `()`, got `u32` - | -note: previous use here - --> $DIR/inference-cycle.rs:11:5 - | -LL | pub fn foo() -> Foo { - | ^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0391`. 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..5fef79d0917d6 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 @@ -1,11 +1,11 @@ error: higher-ranked subtype error - --> $DIR/issue-57611-trait-alias.rs:21:9 + --> $DIR/issue-57611-trait-alias.rs:20:9 | LL | |x| x | ^^^^^ error: higher-ranked subtype error - --> $DIR/issue-57611-trait-alias.rs:21:9 + --> $DIR/issue-57611-trait-alias.rs:20:9 | LL | |x| x | ^^^^^ @@ -19,7 +19,7 @@ LL | type Bar = impl Baz; = 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 + --> $DIR/issue-57611-trait-alias.rs:20:9 | LL | |x| x | ^^^^^ 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 91aa77f2268b2..7c6e764248479 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,7 +15,6 @@ struct X; impl Foo for X { type Bar = impl Baz; - //~^ ERROR could not find defining uses fn bar(&self) -> Self::Bar { |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 c684a8bf6b01f..45329ea292dcf 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,5 +1,5 @@ error: implementation of `FnOnce` is not general enough - --> $DIR/issue-57611-trait-alias.rs:21:9 + --> $DIR/issue-57611-trait-alias.rs:20:9 | LL | |x| x | ^^^^^ implementation of `FnOnce` is not general enough @@ -7,11 +7,5 @@ LL | |x| x = 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` -error: could not find defining uses - --> $DIR/issue-57611-trait-alias.rs:17:16 - | -LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error 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 f2ecd5a455bfd..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,7 +8,6 @@ trait Bug { impl Bug for &() { type Item = impl Bug; //~ ERROR `impl Trait` in type aliases is unstable - //~^ ERROR could not find defining uses const FUN: fn() -> Self::Item = || (); //~^ ERROR the trait bound `(): Bug` is not satisfied 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 fbe071ac85773..3666b6e97ecfd 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60371.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60371.stderr @@ -8,7 +8,7 @@ LL | type Item = impl Bug; = 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:13:40 + --> $DIR/issue-60371.rs:12:40 | LL | const FUN: fn() -> Self::Item = || (); | ^^ the trait `Bug` is not implemented for `()` @@ -16,13 +16,7 @@ LL | const FUN: fn() -> Self::Item = || (); = help: the following implementations were found: <&() as Bug> -error: could not find defining uses - --> $DIR/issue-60371.rs:10:17 - | -LL | type Item = impl 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 e09e1a3afed69..057a908bbee74 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63279.rs +++ b/src/test/ui/type-alias-impl-trait/issue-63279.rs @@ -3,7 +3,6 @@ #![feature(type_alias_impl_trait)] type Closure = impl FnOnce(); -//~^ ERROR could not find defining uses fn c() -> Closure { || -> Closure { || () } 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 810c99c84bc4c..950d9bbf245ca 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63279.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-63279.stderr @@ -1,5 +1,5 @@ error[E0277]: expected a `FnOnce<()>` closure, found `()` - --> $DIR/issue-63279.rs:9:11 + --> $DIR/issue-63279.rs:8:11 | LL | || -> Closure { || () } | ^^^^^^^ expected an `FnOnce<()>` closure, found `()` @@ -8,16 +8,16 @@ LL | || -> Closure { || () } = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` error[E0308]: mismatched types - --> $DIR/issue-63279.rs:9:21 + --> $DIR/issue-63279.rs:8:21 | LL | || -> Closure { || () } | ^^^^^ expected `()`, found closure | = note: expected unit type `()` - found closure `[closure@$DIR/issue-63279.rs:9:21: 9:26]` + found closure `[closure@$DIR/issue-63279.rs:8:21: 8:26]` error[E0308]: mismatched types - --> $DIR/issue-63279.rs:9:5 + --> $DIR/issue-63279.rs:8:5 | LL | type Closure = impl FnOnce(); | ------------- the expected opaque type @@ -26,15 +26,9 @@ LL | || -> Closure { || () } | ^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found closure | = note: expected opaque type `impl FnOnce()` - found closure `[closure@$DIR/issue-63279.rs:9:5: 9:28]` + found closure `[closure@$DIR/issue-63279.rs:8:5: 8:28]` -error: could not find defining uses - --> $DIR/issue-63279.rs:5:16 - | -LL | type Closure = impl FnOnce(); - | ^^^^^^^^^^^^^ - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. 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 eceaef30e0429..ad641eaa00d38 100644 --- a/src/test/ui/type-alias-impl-trait/issue-74280.rs +++ b/src/test/ui/type-alias-impl-trait/issue-74280.rs @@ -3,7 +3,6 @@ #![feature(type_alias_impl_trait)] type Test = impl Copy; -//~^ ERROR could not find defining uses fn test() -> Test { let y = || -> Test { () }; 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 db8c5b7a72bef..c11585db077e2 100644 --- a/src/test/ui/type-alias-impl-trait/issue-74280.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-74280.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-74280.rs:10:5 + --> $DIR/issue-74280.rs:9:5 | LL | type Test = impl Copy; | --------- the expected opaque type @@ -10,12 +10,6 @@ LL | 7 = note: expected opaque type `impl Copy` found type `{integer}` -error: could not find defining uses - --> $DIR/issue-74280.rs:5:13 - | -LL | type Test = impl Copy; - | ^^^^^^^^^ - -error: aborting due to 2 previous errors +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 49ce39c57d193..46bac5a34f5c0 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,7 +5,6 @@ #![feature(type_alias_impl_trait)] type X = impl Into<&'static A>; -//~^ ERROR could not find defining uses fn f(a: &'static A, b: B) -> (X, X) { (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 4c3f527a21421..f4d8b4509d43d 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,5 +1,5 @@ error[E0277]: the trait bound `&'static B: From<&A>` is not satisfied - --> $DIR/multiple-def-uses-in-one-fn.rs:11:9 + --> $DIR/multiple-def-uses-in-one-fn.rs:10:9 | LL | (a, a) | ^ the trait `From<&A>` is not implemented for `&'static B` @@ -10,12 +10,6 @@ help: consider introducing a `where` bound, but there might be an alternative be LL | fn f(a: &'static A, b: B) -> (X, X) where &'static B: From<&A> { | ++++++++++++++++++++++++++ -error: could not find defining uses - --> $DIR/multiple-def-uses-in-one-fn.rs:7:16 - | -LL | type X = impl Into<&'static A>; - | ^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs index 78a665d97a0ea..d51c4185fbc4a 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs @@ -4,7 +4,6 @@ use std::fmt::Debug; type FooX = impl Debug; -//~^ ERROR could not find defining uses trait Foo { } diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr index d9585621d2dd2..630328afc52c4 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/nested-tait-inference.rs:15:5 + --> $DIR/nested-tait-inference.rs:14:5 | LL | () | ^^ the trait `Foo` is not implemented for `()` @@ -7,12 +7,6 @@ LL | () = help: the following implementations were found: <() as Foo<()>> -error: could not find defining uses - --> $DIR/nested-tait-inference.rs:6:13 - | -LL | type FooX = impl Debug; - | ^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs index 4cbbe01ed5132..00d835d3ca774 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs @@ -4,7 +4,6 @@ use std::fmt::Debug; type FooX = impl Debug; -//~^ ERROR could not find defining uses trait Foo {} diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr index e08488287f5cd..1b04ea2bf167c 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/nested-tait-inference2.rs:15:5 + --> $DIR/nested-tait-inference2.rs:14:5 | LL | () | ^^ the trait `Foo` is not implemented for `()` @@ -8,12 +8,6 @@ LL | () <() as Foo<()>> <() as Foo> -error: could not find defining uses - --> $DIR/nested-tait-inference2.rs:6:13 - | -LL | type FooX = impl Debug; - | ^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. From 7fd9c7e6de6d214abd5cc6c2c28231e351a807d5 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Jan 2022 16:15:58 +0000 Subject: [PATCH 35/53] undo a useless change --- src/test/ui/async-await/async-error-span.rs | 3 ++- src/test/ui/async-await/async-error-span.stderr | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/test/ui/async-await/async-error-span.rs b/src/test/ui/async-await/async-error-span.rs index 338483ff6acdc..86d459bf084b1 100644 --- a/src/test/ui/async-await/async-error-span.rs +++ b/src/test/ui/async-await/async-error-span.rs @@ -5,7 +5,8 @@ use std::future::Future; fn get_future() -> impl Future { - panic!() //~^ ERROR `()` is not a future +//~^ ERROR `()` is not a future + panic!() } async fn foo() { diff --git a/src/test/ui/async-await/async-error-span.stderr b/src/test/ui/async-await/async-error-span.stderr index 18e8dd940fa06..7d4447b6d5578 100644 --- a/src/test/ui/async-await/async-error-span.stderr +++ b/src/test/ui/async-await/async-error-span.stderr @@ -8,13 +8,13 @@ LL | fn get_future() -> impl Future { = note: () must be a future or must implement `IntoFuture` to be awaited error[E0698]: type inside `async fn` body must be known in this context - --> $DIR/async-error-span.rs:12:9 + --> $DIR/async-error-span.rs:13:9 | LL | let a; | ^ cannot infer type | note: the type is part of the `async fn` body because of this `await` - --> $DIR/async-error-span.rs:13:17 + --> $DIR/async-error-span.rs:14:17 | LL | get_future().await; | ^^^^^^ From 5518d1931d4035a207438d625464dce9c3171d54 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Jan 2022 16:22:22 +0000 Subject: [PATCH 36/53] Guess head span of async blocks --- .../src/traits/error_reporting/suggestions.rs | 1 + .../ui/async-await/issue-64130-4-async-move.stderr | 10 ++-------- src/test/ui/async-await/issue-70818.stderr | 2 +- .../ui/async-await/issue-70935-complex-spans.stderr | 9 ++------- 4 files changed, 6 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 6634f3e364d32..9eed03bb22384 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1680,6 +1680,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { )); let original_span = err.span.primary_span().unwrap(); + let original_span = self.tcx.sess.source_map().guess_head_span(original_span); let mut span = MultiSpan::from_span(original_span); let message = outer_generator diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr index 2d4327f4ea8ab..3a84907e0c04b 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.stderr +++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr @@ -1,14 +1,8 @@ error: future cannot be sent between threads safely --> $DIR/issue-64130-4-async-move.rs:17:5 | -LL | / async move { -LL | | -LL | | match client.status() { -LL | | 200 => { -... | -LL | | } -LL | | } - | |_____^ future created by async block is not `Send` +LL | async move { + | ^^^^^^^^^^ future created by async block is not `Send` | = help: the trait `Sync` is not implemented for `(dyn Any + Send + 'static)` note: future is not `Send` as this value is used across an await diff --git a/src/test/ui/async-await/issue-70818.stderr b/src/test/ui/async-await/issue-70818.stderr index 3fc08c18bc0eb..cb50c70f99847 100644 --- a/src/test/ui/async-await/issue-70818.stderr +++ b/src/test/ui/async-await/issue-70818.stderr @@ -2,7 +2,7 @@ error: future cannot be sent between threads safely --> $DIR/issue-70818.rs:5:5 | LL | async { (ty, ty1) } - | ^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` + | ^^^^^ future created by async block is not `Send` | note: captured value is not `Send` --> $DIR/issue-70818.rs:5:18 diff --git a/src/test/ui/async-await/issue-70935-complex-spans.stderr b/src/test/ui/async-await/issue-70935-complex-spans.stderr index c7b6893afd6f1..ad61f21741bb5 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.stderr @@ -1,13 +1,8 @@ error: future cannot be sent between threads safely --> $DIR/issue-70935-complex-spans.rs:11:5 | -LL | / async move { -LL | | -LL | | baz(|| async{ -LL | | foo(tx.clone()); -LL | | }).await; -LL | | } - | |_____^ future created by async block is not `Send` +LL | async move { + | ^^^^^^^^^^ future created by async block is not `Send` | = help: the trait `Sync` is not implemented for `Sender` note: future is not `Send` as this value is used across an await From 4d2e9651060c984d18cf8863ceacf215ec00446c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Jan 2022 16:34:28 +0000 Subject: [PATCH 37/53] Make a span more useful --- .../src/traits/error_reporting/suggestions.rs | 1 + src/test/ui/generator/issue-88653.stderr | 17 +++++------------ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 9eed03bb22384..51b8c9aca78b3 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1328,6 +1328,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ty::Generator(..) => "generator", _ => "function", }; + let span = self.tcx.sess.source_map().guess_head_span(span); let mut err = struct_span_err!( self.tcx.sess, span, diff --git a/src/test/ui/generator/issue-88653.stderr b/src/test/ui/generator/issue-88653.stderr index a44e273f854ce..eaa90a8e60a23 100644 --- a/src/test/ui/generator/issue-88653.stderr +++ b/src/test/ui/generator/issue-88653.stderr @@ -1,18 +1,11 @@ error[E0631]: type mismatch in generator arguments --> $DIR/issue-88653.rs:9:5 | -LL | |bar| { - | ^---- - | | - | _____found signature of `fn(bool) -> _` - | | -LL | | -LL | | -LL | | -... | -LL | | } -LL | | } - | |_____^ expected signature of `fn((bool,)) -> _` +LL | |bar| { + | ^^^^^ + | | + | expected signature of `fn((bool,)) -> _` + | found signature of `fn(bool) -> _` error: aborting due to previous error From 29c873243688ed06488cdbb2c693712dafe80156 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 28 Jan 2022 16:30:46 +0000 Subject: [PATCH 38/53] Make the error for opaque types that have no hidden types a bit informative --- compiler/rustc_typeck/src/collect/type_of.rs | 7 ++++++- .../ui/generic-associated-types/issue-87258_a.rs | 2 +- .../ui/generic-associated-types/issue-87258_a.stderr | 4 +++- .../ui/generic-associated-types/issue-87258_b.rs | 2 +- .../ui/generic-associated-types/issue-87258_b.stderr | 4 +++- src/test/ui/generic-associated-types/issue-88595.rs | 2 +- .../ui/generic-associated-types/issue-88595.stderr | 4 +++- ...e-type-alias-impl-trait-declaration-too-subtle.rs | 4 ++-- ...pe-alias-impl-trait-declaration-too-subtle.stderr | 8 ++++++-- .../ui/impl-trait/two_tait_defining_each_other2.rs | 2 +- .../impl-trait/two_tait_defining_each_other2.stderr | 4 +++- src/test/ui/lint/inline-trait-and-foreign-items.rs | 2 +- .../ui/lint/inline-trait-and-foreign-items.stderr | 4 +++- src/test/ui/never_type/impl_trait_fallback3.rs | 2 +- src/test/ui/never_type/impl_trait_fallback3.stderr | 4 +++- src/test/ui/save-analysis/issue-68621.rs | 2 +- src/test/ui/save-analysis/issue-68621.stderr | 4 +++- .../ui/type-alias-impl-trait/bound_reduction2.rs | 2 +- .../ui/type-alias-impl-trait/bound_reduction2.stderr | 4 +++- .../ui/type-alias-impl-trait/bounds-are-checked.rs | 2 +- .../type-alias-impl-trait/bounds-are-checked.stderr | 4 +++- .../declared_but_never_defined.rs | 2 +- .../declared_but_never_defined.stderr | 4 +++- .../declared_but_not_defined_in_scope.rs | 2 +- .../declared_but_not_defined_in_scope.stderr | 4 +++- .../generic_duplicate_lifetime_param.rs | 2 +- .../generic_duplicate_lifetime_param.stderr | 4 +++- .../generic_duplicate_param_use.rs | 6 +++--- .../generic_duplicate_param_use.stderr | 12 +++++++++--- .../type-alias-impl-trait/generic_nondefining_use.rs | 6 +++--- .../generic_nondefining_use.stderr | 12 +++++++++--- src/test/ui/type-alias-impl-trait/issue-60564.rs | 2 +- src/test/ui/type-alias-impl-trait/issue-60564.stderr | 4 +++- .../issue-68368-non-defining-use-2.rs | 2 +- .../issue-68368-non-defining-use-2.stderr | 4 +++- .../issue-68368-non-defining-use.rs | 2 +- .../issue-68368-non-defining-use.stderr | 4 +++- .../type-alias-impl-trait/nested-tait-inference3.rs | 2 +- .../nested-tait-inference3.stderr | 4 +++- .../no_inferrable_concrete_type.rs | 4 ++-- .../no_inferrable_concrete_type.stderr | 4 +++- .../type-alias-impl-trait-with-cycle-error.rs | 2 +- .../type-alias-impl-trait-with-cycle-error.stderr | 4 +++- .../type-alias-impl-trait-with-cycle-error2.rs | 2 +- .../type-alias-impl-trait-with-cycle-error2.stderr | 4 +++- 45 files changed, 115 insertions(+), 56 deletions(-) diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 67a8ae4c1f778..912a16ffb8a13 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -724,7 +724,12 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { Some((_, ty)) => ty, None => { let span = tcx.def_span(def_id); - tcx.sess.span_err(span, "could not find defining uses"); + let name = tcx.item_name(tcx.parent(def_id.to_def_id()).unwrap()); + let label = format!( + "`{}` must be used in combination with a concrete type within the same module", + name + ); + tcx.sess.struct_span_err(span, "unconstrained opaque type").note(&label).emit(); tcx.ty_error() } } diff --git a/src/test/ui/generic-associated-types/issue-87258_a.rs b/src/test/ui/generic-associated-types/issue-87258_a.rs index 16b56db75debc..c65f3fb2aa0a1 100644 --- a/src/test/ui/generic-associated-types/issue-87258_a.rs +++ b/src/test/ui/generic-associated-types/issue-87258_a.rs @@ -16,7 +16,7 @@ pub trait Trait2 { impl<'c, S: Trait2> Trait2 for &'c mut S { type FooFuture<'a> = impl Trait1; - //~^ ERROR could not find defining uses + //~^ ERROR unconstrained opaque type fn foo<'a>() -> Self::FooFuture<'a> { Struct(unimplemented!()) } diff --git a/src/test/ui/generic-associated-types/issue-87258_a.stderr b/src/test/ui/generic-associated-types/issue-87258_a.stderr index 25166a5f5e129..db3a5c819cbf3 100644 --- a/src/test/ui/generic-associated-types/issue-87258_a.stderr +++ b/src/test/ui/generic-associated-types/issue-87258_a.stderr @@ -1,8 +1,10 @@ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/issue-87258_a.rs:18:26 | LL | type FooFuture<'a> = impl Trait1; | ^^^^^^^^^^^ + | + = note: `FooFuture` must be used in combination with a concrete type within the same module error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-87258_b.rs b/src/test/ui/generic-associated-types/issue-87258_b.rs index 30bdc29474eb6..f59e0d7665942 100644 --- a/src/test/ui/generic-associated-types/issue-87258_b.rs +++ b/src/test/ui/generic-associated-types/issue-87258_b.rs @@ -15,7 +15,7 @@ pub trait Trait2 { } type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1; -//~^ ERROR could not find defining uses +//~^ ERROR unconstrained opaque type impl<'c, S: Trait2> Trait2 for &'c mut S { type FooFuture<'a> = Helper<'c, 'a, S>; diff --git a/src/test/ui/generic-associated-types/issue-87258_b.stderr b/src/test/ui/generic-associated-types/issue-87258_b.stderr index ea30117201e0f..9faccc96124bc 100644 --- a/src/test/ui/generic-associated-types/issue-87258_b.stderr +++ b/src/test/ui/generic-associated-types/issue-87258_b.stderr @@ -1,8 +1,10 @@ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/issue-87258_b.rs:17:49 | LL | type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1; | ^^^^^^^^^^^ + | + = note: `Helper` must be used in combination with a concrete type within the same module error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-88595.rs b/src/test/ui/generic-associated-types/issue-88595.rs index e397390783f66..c6cde3aa065e7 100644 --- a/src/test/ui/generic-associated-types/issue-88595.rs +++ b/src/test/ui/generic-associated-types/issue-88595.rs @@ -18,7 +18,7 @@ struct C; impl<'a> A<'a> for C { type B<'b> = impl Clone; //~^ ERROR: lifetime bound not satisfied - //~| ERROR: could not find defining uses + //~| ERROR: unconstrained opaque type fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope } diff --git a/src/test/ui/generic-associated-types/issue-88595.stderr b/src/test/ui/generic-associated-types/issue-88595.stderr index 6c3a75c85714a..58afc42fdea76 100644 --- a/src/test/ui/generic-associated-types/issue-88595.stderr +++ b/src/test/ui/generic-associated-types/issue-88595.stderr @@ -29,11 +29,13 @@ LL | impl<'a> A<'a> for C { LL | type B<'b> = impl Clone; | ^^ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/issue-88595.rs:19:18 | LL | type B<'b> = impl Clone; | ^^^^^^^^^^ + | + = note: `B` must be used in combination with a concrete type within the same module error: aborting due to 3 previous errors diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs index 162a26593c7f6..a60e34c17b671 100644 --- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs @@ -2,7 +2,7 @@ mod a { type Foo = impl PartialEq<(Foo, i32)>; - //~^ ERROR could not find defining uses + //~^ ERROR unconstrained opaque type struct Bar; @@ -15,7 +15,7 @@ mod a { mod b { type Foo = impl PartialEq<(Foo, i32)>; - //~^ ERROR could not find defining uses + //~^ ERROR unconstrained opaque type struct Bar; diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr index 71c4e3f5949e1..eae7d38d1162b 100644 --- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr @@ -1,14 +1,18 @@ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:4:16 | LL | type Foo = impl PartialEq<(Foo, i32)>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module -error: could not find defining uses +error: unconstrained opaque type --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:17:16 | LL | type Foo = impl PartialEq<(Foo, i32)>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other2.rs b/src/test/ui/impl-trait/two_tait_defining_each_other2.rs index 88a76089b82d1..295e2375428aa 100644 --- a/src/test/ui/impl-trait/two_tait_defining_each_other2.rs +++ b/src/test/ui/impl-trait/two_tait_defining_each_other2.rs @@ -1,7 +1,7 @@ #![feature(type_alias_impl_trait)] type A = impl Foo; -//~^ ERROR could not find defining uses +//~^ ERROR unconstrained opaque type type B = impl Foo; trait Foo {} diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other2.stderr b/src/test/ui/impl-trait/two_tait_defining_each_other2.stderr index 5a0cff527b6e9..e48a5724a7fa5 100644 --- a/src/test/ui/impl-trait/two_tait_defining_each_other2.stderr +++ b/src/test/ui/impl-trait/two_tait_defining_each_other2.stderr @@ -1,8 +1,10 @@ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/two_tait_defining_each_other2.rs:3:10 | LL | type A = impl Foo; | ^^^^^^^^ + | + = note: `A` must be used in combination with a concrete type within the same module error: aborting due to previous error diff --git a/src/test/ui/lint/inline-trait-and-foreign-items.rs b/src/test/ui/lint/inline-trait-and-foreign-items.rs index 6321b3c76e4d1..13dab7ed954f8 100644 --- a/src/test/ui/lint/inline-trait-and-foreign-items.rs +++ b/src/test/ui/lint/inline-trait-and-foreign-items.rs @@ -23,7 +23,7 @@ impl Trait for () { type T = Self; #[inline] //~ ERROR attribute should be applied to function or closure - type U = impl Trait; //~ ERROR could not find defining uses + type U = impl Trait; //~ ERROR unconstrained opaque type } extern "C" { diff --git a/src/test/ui/lint/inline-trait-and-foreign-items.stderr b/src/test/ui/lint/inline-trait-and-foreign-items.stderr index 6ac884c12ceb9..fc7e89e4f4cce 100644 --- a/src/test/ui/lint/inline-trait-and-foreign-items.stderr +++ b/src/test/ui/lint/inline-trait-and-foreign-items.stderr @@ -61,11 +61,13 @@ LL | #[inline] LL | type T; | ------- not a function or closure -error: could not find defining uses +error: unconstrained opaque type --> $DIR/inline-trait-and-foreign-items.rs:26:14 | LL | type U = impl Trait; | ^^^^^^^^^^ + | + = note: `U` must be used in combination with a concrete type within the same module error: aborting due to 6 previous errors; 2 warnings emitted diff --git a/src/test/ui/never_type/impl_trait_fallback3.rs b/src/test/ui/never_type/impl_trait_fallback3.rs index a44402a22b956..26ce9b93105e6 100644 --- a/src/test/ui/never_type/impl_trait_fallback3.rs +++ b/src/test/ui/never_type/impl_trait_fallback3.rs @@ -7,7 +7,7 @@ trait T { } type Foo = impl T; -//~^ ERROR could not find defining uses +//~^ ERROR unconstrained opaque type fn a() -> Foo { // This is not a defining use, it doesn't actually constrain the opaque type. diff --git a/src/test/ui/never_type/impl_trait_fallback3.stderr b/src/test/ui/never_type/impl_trait_fallback3.stderr index de04758a1e311..121019d5f69ae 100644 --- a/src/test/ui/never_type/impl_trait_fallback3.stderr +++ b/src/test/ui/never_type/impl_trait_fallback3.stderr @@ -1,8 +1,10 @@ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/impl_trait_fallback3.rs:9:12 | LL | type Foo = impl T; | ^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module error: aborting due to previous error diff --git a/src/test/ui/save-analysis/issue-68621.rs b/src/test/ui/save-analysis/issue-68621.rs index 96af085c5b6b8..30479580f11a3 100644 --- a/src/test/ui/save-analysis/issue-68621.rs +++ b/src/test/ui/save-analysis/issue-68621.rs @@ -11,7 +11,7 @@ trait Service { struct Struct; impl Service for Struct { - type Future = impl Trait; //~ ERROR: could not find defining uses + type Future = impl Trait; //~ ERROR: unconstrained opaque type } fn main() {} diff --git a/src/test/ui/save-analysis/issue-68621.stderr b/src/test/ui/save-analysis/issue-68621.stderr index 3af6d0a3e076e..4a4bf9a6996bc 100644 --- a/src/test/ui/save-analysis/issue-68621.stderr +++ b/src/test/ui/save-analysis/issue-68621.stderr @@ -1,8 +1,10 @@ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/issue-68621.rs:14:19 | LL | type Future = impl Trait; | ^^^^^^^^^^ + | + = note: `Future` must be used in combination with a concrete type within the same module error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs index ba780e301edc6..f3d12d02ccd3a 100644 --- a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs +++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs @@ -7,7 +7,7 @@ trait TraitWithAssoc { } type Foo = impl Trait; -//~^ ERROR could not find defining uses +//~^ ERROR unconstrained opaque type trait Trait {} diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr index 21e79ee36a635..f309fa53b1a31 100644 --- a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr +++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr @@ -10,11 +10,13 @@ note: used non-generic type `::Assoc` for generic parameter LL | type Foo = impl Trait; | ^ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/bound_reduction2.rs:9:15 | LL | type Foo = impl Trait; | ^^^^^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs b/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs index d694d3822388e..ce6ed8080092c 100644 --- a/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs @@ -4,7 +4,7 @@ #![feature(type_alias_impl_trait)] type X<'a> = impl Into<&'static str> + From<&'a str>; -//~^ ERROR could not find defining uses +//~^ ERROR unconstrained opaque type fn f<'a: 'static>(t: &'a str) -> X<'a> { //~^ WARNING unnecessary lifetime parameter diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr index 11bc926c961a5..34141c9c8a64e 100644 --- a/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr @@ -15,11 +15,13 @@ LL | type X<'a> = impl Into<&'static str> + From<&'a str>; LL | t | ^ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/bounds-are-checked.rs:6:14 | LL | type X<'a> = impl Into<&'static str> + From<&'a str>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `X` must be used in combination with a concrete type within the same module error: aborting due to 2 previous errors; 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/declared_but_never_defined.rs b/src/test/ui/type-alias-impl-trait/declared_but_never_defined.rs index c4bf56a919721..6febd07157aa6 100644 --- a/src/test/ui/type-alias-impl-trait/declared_but_never_defined.rs +++ b/src/test/ui/type-alias-impl-trait/declared_but_never_defined.rs @@ -3,4 +3,4 @@ fn main() {} // declared but never defined -type Bar = impl std::fmt::Debug; //~ ERROR could not find defining uses +type Bar = impl std::fmt::Debug; //~ ERROR unconstrained opaque type diff --git a/src/test/ui/type-alias-impl-trait/declared_but_never_defined.stderr b/src/test/ui/type-alias-impl-trait/declared_but_never_defined.stderr index 21c2e8a9db618..60bc24320a301 100644 --- a/src/test/ui/type-alias-impl-trait/declared_but_never_defined.stderr +++ b/src/test/ui/type-alias-impl-trait/declared_but_never_defined.stderr @@ -1,8 +1,10 @@ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/declared_but_never_defined.rs:6:12 | LL | type Bar = impl std::fmt::Debug; | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `Bar` must be used in combination with a concrete type within the same module error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs index 7ea517eb734a4..5bda5f0fceaaa 100644 --- a/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs +++ b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs @@ -4,7 +4,7 @@ fn main() {} mod boo { // declared in module but not defined inside of it - pub type Boo = impl ::std::fmt::Debug; //~ ERROR could not find defining uses + pub type Boo = impl ::std::fmt::Debug; //~ ERROR unconstrained opaque type } fn bomp() -> boo::Boo { diff --git a/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr index 4564ef6b8f6a0..d61561d3ea937 100644 --- a/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr +++ b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr @@ -1,8 +1,10 @@ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/declared_but_not_defined_in_scope.rs:7:20 | LL | pub type Boo = impl ::std::fmt::Debug; | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `Boo` must be used in combination with a concrete type within the same module error[E0308]: mismatched types --> $DIR/declared_but_not_defined_in_scope.rs:11:5 diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs index e7768c246c207..efb681e7e88e3 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs @@ -3,7 +3,7 @@ fn main() {} type Two<'a, 'b> = impl std::fmt::Debug; -//~^ ERROR could not find defining uses +//~^ ERROR unconstrained opaque type fn one<'a>(t: &'a ()) -> Two<'a, 'a> { t diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr index bcd3a71dc18fb..f68ab3de2ba22 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr @@ -10,11 +10,13 @@ note: lifetime used multiple times LL | type Two<'a, 'b> = impl std::fmt::Debug; | ^^ ^^ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/generic_duplicate_lifetime_param.rs:5:20 | LL | type Two<'a, 'b> = impl std::fmt::Debug; | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `Two` must be used in combination with a concrete type within the same module error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs index e854434a59fc9..e67ca695585ae 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs @@ -6,11 +6,11 @@ fn main() {} // test that unused generic parameters are ok type TwoTys = impl Debug; -//~^ ERROR could not find defining uses +//~^ ERROR unconstrained opaque type type TwoLifetimes<'a, 'b> = impl Debug; -//~^ ERROR could not find defining uses +//~^ ERROR unconstrained opaque type type TwoConsts = impl Debug; -//~^ ERROR could not find defining uses +//~^ ERROR unconstrained opaque type fn one_ty(t: T) -> TwoTys { t diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr index 48b3a4d287a7a..fb0b4104330bc 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr @@ -10,11 +10,13 @@ note: type used multiple times LL | type TwoTys = impl Debug; | ^ ^ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/generic_duplicate_param_use.rs:8:21 | LL | type TwoTys = impl Debug; | ^^^^^^^^^^ + | + = note: `TwoTys` must be used in combination with a concrete type within the same module error: non-defining opaque type use in defining scope --> $DIR/generic_duplicate_param_use.rs:21:5 @@ -28,11 +30,13 @@ note: lifetime used multiple times LL | type TwoLifetimes<'a, 'b> = impl Debug; | ^^ ^^ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/generic_duplicate_param_use.rs:10:29 | LL | type TwoLifetimes<'a, 'b> = impl Debug; | ^^^^^^^^^^ + | + = note: `TwoLifetimes` must be used in combination with a concrete type within the same module error: non-defining opaque type use in defining scope --> $DIR/generic_duplicate_param_use.rs:26:5 @@ -46,11 +50,13 @@ note: constant used multiple times LL | type TwoConsts = impl Debug; | ^ ^ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/generic_duplicate_param_use.rs:12:50 | LL | type TwoConsts = impl Debug; | ^^^^^^^^^^ + | + = note: `TwoConsts` must be used in combination with a concrete type within the same module error: aborting due to 6 previous errors diff --git a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs index 2fe5c68ab576f..dd7817a8f7d1f 100644 --- a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs +++ b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs @@ -5,11 +5,11 @@ use std::fmt::Debug; fn main() {} type OneTy = impl Debug; -//~^ ERROR could not find defining uses +//~^ ERROR unconstrained opaque type type OneLifetime<'a> = impl Debug; -//~^ ERROR could not find defining uses +//~^ ERROR unconstrained opaque type type OneConst = impl Debug; -//~^ ERROR could not find defining uses +//~^ ERROR unconstrained opaque type // Not defining uses, because they doesn't define *all* possible generics. diff --git a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr index 1b2084b630f29..6bc02c2989a54 100644 --- a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr @@ -10,11 +10,13 @@ note: used non-generic type `u32` for generic parameter LL | type OneTy = impl Debug; | ^ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/generic_nondefining_use.rs:7:17 | LL | type OneTy = impl Debug; | ^^^^^^^^^^ + | + = note: `OneTy` must be used in combination with a concrete type within the same module error: non-defining opaque type use in defining scope --> $DIR/generic_nondefining_use.rs:22:5 @@ -25,11 +27,13 @@ LL | type OneLifetime<'a> = impl Debug; LL | 6u32 | ^^^^ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/generic_nondefining_use.rs:9:24 | LL | type OneLifetime<'a> = impl Debug; | ^^^^^^^^^^ + | + = note: `OneLifetime` must be used in combination with a concrete type within the same module error: non-defining opaque type use in defining scope --> $DIR/generic_nondefining_use.rs:27:5 @@ -43,11 +47,13 @@ note: used non-generic constant `123_usize` for generic parameter LL | type OneConst = impl Debug; | ^ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/generic_nondefining_use.rs:11:33 | LL | type OneConst = impl Debug; | ^^^^^^^^^^ + | + = note: `OneConst` must be used in combination with a concrete type within the same module error: aborting due to 6 previous errors diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.rs b/src/test/ui/type-alias-impl-trait/issue-60564.rs index e645663c3420a..fd254724fb554 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60564.rs +++ b/src/test/ui/type-alias-impl-trait/issue-60564.rs @@ -6,7 +6,7 @@ trait IterBits { } type IterBitsIter = impl std::iter::Iterator; -//~^ ERROR could not find defining uses +//~^ ERROR unconstrained opaque type impl IterBits for T where diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.stderr b/src/test/ui/type-alias-impl-trait/issue-60564.stderr index 0a260a247c082..c5ac477187dd0 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60564.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60564.stderr @@ -10,11 +10,13 @@ note: used non-generic type `u8` for generic parameter LL | type IterBitsIter = impl std::iter::Iterator; | ^ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/issue-60564.rs:8:30 | LL | type IterBitsIter = impl std::iter::Iterator; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `IterBitsIter` must be used in combination with a concrete type within the same module error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs index 2e6354088ac5a..7f25d320677ed 100644 --- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs @@ -5,7 +5,7 @@ #![feature(type_alias_impl_trait)] trait Trait {} type Alias<'a, U> = impl Trait; -//~^ ERROR could not find defining uses +//~^ ERROR unconstrained opaque type fn f<'a>() -> Alias<'a, ()> {} //~^ ERROR non-defining opaque type use in defining scope diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr index 3524d1ea8a4d5..4afa903969f26 100644 --- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr @@ -10,11 +10,13 @@ note: used non-generic type `()` for generic parameter LL | type Alias<'a, U> = impl Trait; | ^ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/issue-68368-non-defining-use-2.rs:7:21 | LL | type Alias<'a, U> = impl Trait; | ^^^^^^^^^^^^^ + | + = note: `Alias` must be used in combination with a concrete type within the same module error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs index 3addd8dcc4fb3..b2b8a68bd7525 100644 --- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs @@ -5,7 +5,7 @@ #![feature(type_alias_impl_trait)] trait Trait {} type Alias<'a, U> = impl Trait; -//~^ ERROR could not find defining uses +//~^ ERROR unconstrained opaque type fn f<'a>() -> Alias<'a, ()> {} //~^ ERROR non-defining opaque type use in defining scope diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr index 3f7c57f721d55..94dc3b7c2b047 100644 --- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr @@ -10,11 +10,13 @@ note: used non-generic type `()` for generic parameter LL | type Alias<'a, U> = impl Trait; | ^ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/issue-68368-non-defining-use.rs:7:21 | LL | type Alias<'a, U> = impl Trait; | ^^^^^^^^^^^^^ + | + = note: `Alias` must be used in combination with a concrete type within the same module error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs index e884fa0a48d67..fbab5470b4f6d 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs @@ -4,7 +4,7 @@ use std::fmt::Debug; type FooX = impl Debug; -//~^ could not find defining uses +//~^ unconstrained opaque type trait Foo { } diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr index 6bbed0032b515..b1d947a9ccf4e 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr @@ -1,8 +1,10 @@ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/nested-tait-inference3.rs:6:13 | LL | type FooX = impl Debug; | ^^^^^^^^^^ + | + = note: `FooX` must be used in combination with a concrete type within the same module error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs index 1197c7bc58ece..fa578eced5f2b 100644 --- a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs +++ b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs @@ -1,9 +1,9 @@ // Issue 52985: user code provides no use case that allows a type alias `impl Trait` -// We now emit a 'could not find defining uses' error +// We now emit a 'unconstrained opaque type' error #![feature(type_alias_impl_trait)] -type Foo = impl Copy; //~ could not find defining uses +type Foo = impl Copy; //~ unconstrained opaque type // make compiler happy about using 'Foo' fn bar(x: Foo) -> Foo { diff --git a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr index 61025e846921e..009935347e66c 100644 --- a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr +++ b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr @@ -1,8 +1,10 @@ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/no_inferrable_concrete_type.rs:6:12 | LL | type Foo = impl Copy; | ^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs index c009952eab750..e5e7fb677ede9 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs @@ -1,7 +1,7 @@ #![feature(type_alias_impl_trait)] type Foo = impl Fn() -> Foo; -//~^ ERROR: could not find defining uses +//~^ ERROR: unconstrained opaque type fn crash(x: Foo) -> Foo { x diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr index 726f4ea6e00f7..a770eeac39b7d 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr @@ -1,8 +1,10 @@ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/type-alias-impl-trait-with-cycle-error.rs:3:12 | LL | type Foo = impl Fn() -> Foo; | ^^^^^^^^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs index f3898bca64b9b..7c7a1b405bcdc 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs @@ -5,7 +5,7 @@ pub trait Bar { } type Foo = impl Bar; -//~^ ERROR: could not find defining uses +//~^ ERROR: unconstrained opaque type fn crash(x: Foo) -> Foo { x diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr index 3947cc4d27055..3f3699ce5324a 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr @@ -1,8 +1,10 @@ -error: could not find defining uses +error: unconstrained opaque type --> $DIR/type-alias-impl-trait-with-cycle-error2.rs:7:12 | LL | type Foo = impl Bar; | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module error: aborting due to previous error From 6560d77a534167a8b86e1e968328cf1f717304dc Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 28 Jan 2022 16:42:29 +0000 Subject: [PATCH 39/53] Bail out early if there already were errors --- .../rustc_trait_selection/src/opaque_types.rs | 15 ++++------- ..._type_does_not_live_long_enough.nll.stderr | 11 +------- .../issue-57611-trait-alias.nll.stderr | 26 +------------------ 3 files changed, 7 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index d3a28c6d3aa35..cd12430a2a249 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -48,6 +48,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { instantiated_ty: Ty<'tcx>, span: Span, ) -> Ty<'tcx> { + if self.is_tainted_by_errors() { + return self.tcx.ty_error(); + } + let OpaqueTypeKey { def_id, substs } = opaque_type_key; // Use substs to build up a reverse map from regions to their @@ -67,7 +71,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // after producing an error for each of them. let definition_ty = instantiated_ty.fold_with(&mut ReverseMapper::new( self.tcx, - self.is_tainted_by_errors(), def_id, map, instantiated_ty, @@ -82,10 +85,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { struct ReverseMapper<'tcx> { tcx: TyCtxt<'tcx>, - /// If errors have already been reported in this fn, we suppress - /// our own errors because they are sometimes derivative. - tainted_by_errors: bool, - opaque_type_def_id: DefId, map: FxHashMap, GenericArg<'tcx>>, map_missing_regions_to_empty: bool, @@ -100,7 +99,6 @@ struct ReverseMapper<'tcx> { impl<'tcx> ReverseMapper<'tcx> { fn new( tcx: TyCtxt<'tcx>, - tainted_by_errors: bool, opaque_type_def_id: DefId, map: FxHashMap, GenericArg<'tcx>>, hidden_ty: Ty<'tcx>, @@ -108,7 +106,6 @@ impl<'tcx> ReverseMapper<'tcx> { ) -> Self { Self { tcx, - tainted_by_errors, opaque_type_def_id, map, map_missing_regions_to_empty: false, @@ -167,9 +164,7 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> { match self.map.get(&r.into()).map(|k| k.unpack()) { Some(GenericArgKind::Lifetime(r1)) => r1, Some(u) => panic!("region mapped to unexpected kind: {:?}", u), - None if self.map_missing_regions_to_empty || self.tainted_by_errors => { - self.tcx.lifetimes.re_root_empty - } + None if self.map_missing_regions_to_empty => self.tcx.lifetimes.re_root_empty, None if generics.parent.is_some() => { if let Some(hidden_ty) = self.hidden_ty.take() { unexpected_hidden_region_diagnostic( 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 ef9756acee058..dc85db66d32ba 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 @@ -24,15 +24,6 @@ LL | t | = help: consider adding an explicit lifetime bound `T: 'static`... -error[E0310]: the parameter type `T` may not live long enough - --> $DIR/generic_type_does_not_live_long_enough.rs:10:24 - | -LL | type WrongGeneric = impl 'static; - | ^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `T: 'static`... - = note: ...so that the type `T` will meet its required lifetime bounds - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0310`. 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 5fef79d0917d6..1538274d45cb2 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:20: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`. From 59d0bff0e63efc7b48e55d6e512848bfc233353e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 28 Jan 2022 17:18:53 +0000 Subject: [PATCH 40/53] Reduce follow-up errors that are not helpful --- .../src/region_infer/opaque_types.rs | 12 ++++++--- .../generic-associated-types/issue-88595.rs | 1 - .../issue-88595.stderr | 12 ++------- .../type-alias-impl-trait/bound_reduction2.rs | 1 - .../bound_reduction2.stderr | 12 ++------- .../bounds-are-checked.rs | 1 - .../bounds-are-checked.stderr | 14 +++------- .../generic_duplicate_lifetime_param.rs | 2 +- .../generic_duplicate_lifetime_param.stderr | 10 +------ .../generic_duplicate_param_use.rs | 6 ++--- .../generic_duplicate_param_use.stderr | 26 +------------------ .../generic_duplicate_param_use2.rs | 5 ---- .../generic_duplicate_param_use2.stderr | 14 +--------- .../generic_duplicate_param_use3.rs | 5 ---- .../generic_duplicate_param_use3.stderr | 18 +++---------- .../generic_duplicate_param_use4.rs | 5 ---- .../generic_duplicate_param_use4.stderr | 14 +--------- .../generic_nondefining_use.rs | 6 ++--- .../generic_nondefining_use.stderr | 26 +------------------ .../ui/type-alias-impl-trait/issue-60564.rs | 1 - .../type-alias-impl-trait/issue-60564.stderr | 12 ++------- .../issue-68368-non-defining-use-2.rs | 2 +- .../issue-68368-non-defining-use-2.stderr | 10 +------ .../issue-68368-non-defining-use.rs | 2 +- .../issue-68368-non-defining-use.stderr | 10 +------ .../not_a_defining_use.rs | 5 ---- .../not_a_defining_use.stderr | 18 +++---------- 27 files changed, 40 insertions(+), 210 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 205578c638acd..139cebe0e43d8 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -58,7 +58,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { ) -> VecMap, Ty<'tcx>> { opaque_ty_decls .into_iter() - .filter_map(|(opaque_type_key, (concrete_type, decl_span, origin))| { + .map(|(opaque_type_key, (concrete_type, decl_span, origin))| { let substs = opaque_type_key.substs; // FIXME: why are the spans in decl_span often DUMMY_SP? let span = decl_span.substitute_dummy(span); @@ -112,8 +112,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { span, ); - check_opaque_type_parameter_valid(infcx.tcx, opaque_type_key, origin, span) - .then_some((opaque_type_key, remapped_type)) + ( + opaque_type_key, + if check_opaque_type_parameter_valid(infcx.tcx, opaque_type_key, origin, span) { + remapped_type + } else { + infcx.tcx.ty_error() + }, + ) }) .collect() } diff --git a/src/test/ui/generic-associated-types/issue-88595.rs b/src/test/ui/generic-associated-types/issue-88595.rs index c6cde3aa065e7..ea1bd2be4529d 100644 --- a/src/test/ui/generic-associated-types/issue-88595.rs +++ b/src/test/ui/generic-associated-types/issue-88595.rs @@ -18,7 +18,6 @@ struct C; impl<'a> A<'a> for C { type B<'b> = impl Clone; //~^ ERROR: lifetime bound not satisfied - //~| ERROR: unconstrained opaque type fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope } diff --git a/src/test/ui/generic-associated-types/issue-88595.stderr b/src/test/ui/generic-associated-types/issue-88595.stderr index 58afc42fdea76..e1d55fa228c2e 100644 --- a/src/test/ui/generic-associated-types/issue-88595.stderr +++ b/src/test/ui/generic-associated-types/issue-88595.stderr @@ -16,7 +16,7 @@ LL | type B<'b> = impl Clone; | ^^ error: non-defining opaque type use in defining scope - --> $DIR/issue-88595.rs:23:35 + --> $DIR/issue-88595.rs:22:35 | LL | fn a(&'a self) -> Self::B<'a> {} | ^^ @@ -29,14 +29,6 @@ LL | impl<'a> A<'a> for C { LL | type B<'b> = impl Clone; | ^^ -error: unconstrained opaque type - --> $DIR/issue-88595.rs:19:18 - | -LL | type B<'b> = impl Clone; - | ^^^^^^^^^^ - | - = note: `B` must be used in combination with a concrete type within the same module - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0478`. diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs index f3d12d02ccd3a..4d2890b5de583 100644 --- a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs +++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs @@ -7,7 +7,6 @@ trait TraitWithAssoc { } type Foo = impl Trait; -//~^ ERROR unconstrained opaque type trait Trait {} diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr index f309fa53b1a31..c405b1f6af205 100644 --- a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr +++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr @@ -1,5 +1,5 @@ error: non-defining opaque type use in defining scope - --> $DIR/bound_reduction2.rs:17:5 + --> $DIR/bound_reduction2.rs:16:5 | LL | () | ^^ @@ -10,13 +10,5 @@ note: used non-generic type `::Assoc` for generic parameter LL | type Foo = impl Trait; | ^ -error: unconstrained opaque type - --> $DIR/bound_reduction2.rs:9:15 - | -LL | type Foo = impl Trait; - | ^^^^^^^^^^^^^ - | - = note: `Foo` must be used in combination with a concrete type within the same module - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs b/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs index ce6ed8080092c..83d22161e4e75 100644 --- a/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs @@ -4,7 +4,6 @@ #![feature(type_alias_impl_trait)] type X<'a> = impl Into<&'static str> + From<&'a str>; -//~^ ERROR unconstrained opaque type fn f<'a: 'static>(t: &'a str) -> X<'a> { //~^ WARNING unnecessary lifetime parameter diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr index 34141c9c8a64e..d87ef2ec79c1a 100644 --- a/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr @@ -1,5 +1,5 @@ warning: unnecessary lifetime parameter `'a` - --> $DIR/bounds-are-checked.rs:9:6 + --> $DIR/bounds-are-checked.rs:8:6 | LL | fn f<'a: 'static>(t: &'a str) -> X<'a> { | ^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | fn f<'a: 'static>(t: &'a str) -> X<'a> { = help: you can use the `'static` lifetime directly, in place of `'a` error: non-defining opaque type use in defining scope - --> $DIR/bounds-are-checked.rs:11:5 + --> $DIR/bounds-are-checked.rs:10:5 | LL | type X<'a> = impl Into<&'static str> + From<&'a str>; | -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type @@ -15,13 +15,5 @@ LL | type X<'a> = impl Into<&'static str> + From<&'a str>; LL | t | ^ -error: unconstrained opaque type - --> $DIR/bounds-are-checked.rs:6:14 - | -LL | type X<'a> = impl Into<&'static str> + From<&'a str>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `X` must be used in combination with a concrete type within the same module - -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs index efb681e7e88e3..c9b9e128f88e2 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs @@ -3,7 +3,7 @@ fn main() {} type Two<'a, 'b> = impl std::fmt::Debug; -//~^ ERROR unconstrained opaque type + fn one<'a>(t: &'a ()) -> Two<'a, 'a> { t diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr index f68ab3de2ba22..222aaea78d982 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr @@ -10,13 +10,5 @@ note: lifetime used multiple times LL | type Two<'a, 'b> = impl std::fmt::Debug; | ^^ ^^ -error: unconstrained opaque type - --> $DIR/generic_duplicate_lifetime_param.rs:5:20 - | -LL | type Two<'a, 'b> = impl std::fmt::Debug; - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: `Two` must be used in combination with a concrete type within the same module - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs index e67ca695585ae..093c1c231861f 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs @@ -6,11 +6,11 @@ fn main() {} // test that unused generic parameters are ok type TwoTys = impl Debug; -//~^ ERROR unconstrained opaque type + type TwoLifetimes<'a, 'b> = impl Debug; -//~^ ERROR unconstrained opaque type + type TwoConsts = impl Debug; -//~^ ERROR unconstrained opaque type + fn one_ty(t: T) -> TwoTys { t diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr index fb0b4104330bc..922e41e0f6883 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr @@ -10,14 +10,6 @@ note: type used multiple times LL | type TwoTys = impl Debug; | ^ ^ -error: unconstrained opaque type - --> $DIR/generic_duplicate_param_use.rs:8:21 - | -LL | type TwoTys = impl Debug; - | ^^^^^^^^^^ - | - = note: `TwoTys` must be used in combination with a concrete type within the same module - error: non-defining opaque type use in defining scope --> $DIR/generic_duplicate_param_use.rs:21:5 | @@ -30,14 +22,6 @@ note: lifetime used multiple times LL | type TwoLifetimes<'a, 'b> = impl Debug; | ^^ ^^ -error: unconstrained opaque type - --> $DIR/generic_duplicate_param_use.rs:10:29 - | -LL | type TwoLifetimes<'a, 'b> = impl Debug; - | ^^^^^^^^^^ - | - = note: `TwoLifetimes` must be used in combination with a concrete type within the same module - error: non-defining opaque type use in defining scope --> $DIR/generic_duplicate_param_use.rs:26:5 | @@ -50,13 +34,5 @@ note: constant used multiple times LL | type TwoConsts = impl Debug; | ^ ^ -error: unconstrained opaque type - --> $DIR/generic_duplicate_param_use.rs:12:50 - | -LL | type TwoConsts = impl Debug; - | ^^^^^^^^^^ - | - = note: `TwoConsts` must be used in combination with a concrete type within the same module - -error: aborting due to 6 previous errors +error: aborting due to 3 previous errors diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs index da9dd5baa3d0f..81bf9770d02a8 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs @@ -8,11 +8,6 @@ fn main() {} type Two = impl Debug; //~^ ERROR `T` doesn't implement `Debug` -fn one(t: T) -> Two { - t - //~^ ERROR non-defining opaque type use in defining scope -} - fn two(t: T, _: U) -> Two { t } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr index e62218fe0832c..84aa260b099b6 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr @@ -1,15 +1,3 @@ -error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use2.rs:12:5 - | -LL | t - | ^ - | -note: type used multiple times - --> $DIR/generic_duplicate_param_use2.rs:8:10 - | -LL | type Two = impl Debug; - | ^ ^ - error[E0277]: `T` doesn't implement `Debug` --> $DIR/generic_duplicate_param_use2.rs:8:18 | @@ -21,6 +9,6 @@ help: consider restricting type parameter `T` LL | type Two = impl Debug; | +++++++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs index b21280e2db56a..c95692182c278 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs @@ -8,11 +8,6 @@ fn main() {} type Two = impl Debug; //~^ ERROR `T` doesn't implement `Debug` -fn one(t: T) -> Two { - t - //~^ ERROR non-defining opaque type use in defining scope -} - fn two(t: T, _: U) -> Two { t } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr index cb4e0f04aa146..e5a70fa8ce56e 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr @@ -1,23 +1,11 @@ -error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use3.rs:12:5 - | -LL | t - | ^ - | -note: type used multiple times - --> $DIR/generic_duplicate_param_use3.rs:8:10 - | -LL | type Two = impl Debug; - | ^ ^ - error: concrete type differs from previous defining opaque type use - --> $DIR/generic_duplicate_param_use3.rs:20:1 + --> $DIR/generic_duplicate_param_use3.rs:15:1 | LL | fn three(_: T, u: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `T`, got `U` | note: previous use here - --> $DIR/generic_duplicate_param_use3.rs:16:1 + --> $DIR/generic_duplicate_param_use3.rs:11:1 | LL | fn two(t: T, _: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,6 +21,6 @@ help: consider restricting type parameter `T` LL | type Two = impl Debug; | +++++++++++++++++ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs index 1e22930a5034b..aee2550e9078a 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs @@ -8,11 +8,6 @@ fn main() {} type Two = impl Debug; //~^ ERROR `U` doesn't implement `Debug` -fn one(t: T) -> Two { - t - //~^ ERROR non-defining opaque type use in defining scope -} - fn three(_: T, u: U) -> Two { u } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr index 64268abce50c0..0491d61030e34 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr @@ -1,15 +1,3 @@ -error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use4.rs:12:5 - | -LL | t - | ^ - | -note: type used multiple times - --> $DIR/generic_duplicate_param_use4.rs:8:10 - | -LL | type Two = impl Debug; - | ^ ^ - error[E0277]: `U` doesn't implement `Debug` --> $DIR/generic_duplicate_param_use4.rs:8:18 | @@ -21,6 +9,6 @@ help: consider restricting type parameter `U` LL | type Two = impl Debug; | +++++++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs index dd7817a8f7d1f..f39741a6a625c 100644 --- a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs +++ b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs @@ -5,11 +5,11 @@ use std::fmt::Debug; fn main() {} type OneTy = impl Debug; -//~^ ERROR unconstrained opaque type + type OneLifetime<'a> = impl Debug; -//~^ ERROR unconstrained opaque type + type OneConst = impl Debug; -//~^ ERROR unconstrained opaque type + // Not defining uses, because they doesn't define *all* possible generics. diff --git a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr index 6bc02c2989a54..36694900c17b4 100644 --- a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr @@ -10,14 +10,6 @@ note: used non-generic type `u32` for generic parameter LL | type OneTy = impl Debug; | ^ -error: unconstrained opaque type - --> $DIR/generic_nondefining_use.rs:7:17 - | -LL | type OneTy = impl Debug; - | ^^^^^^^^^^ - | - = note: `OneTy` must be used in combination with a concrete type within the same module - error: non-defining opaque type use in defining scope --> $DIR/generic_nondefining_use.rs:22:5 | @@ -27,14 +19,6 @@ LL | type OneLifetime<'a> = impl Debug; LL | 6u32 | ^^^^ -error: unconstrained opaque type - --> $DIR/generic_nondefining_use.rs:9:24 - | -LL | type OneLifetime<'a> = impl Debug; - | ^^^^^^^^^^ - | - = note: `OneLifetime` must be used in combination with a concrete type within the same module - error: non-defining opaque type use in defining scope --> $DIR/generic_nondefining_use.rs:27:5 | @@ -47,13 +31,5 @@ note: used non-generic constant `123_usize` for generic parameter LL | type OneConst = impl Debug; | ^ -error: unconstrained opaque type - --> $DIR/generic_nondefining_use.rs:11:33 - | -LL | type OneConst = impl Debug; - | ^^^^^^^^^^ - | - = note: `OneConst` must be used in combination with a concrete type within the same module - -error: aborting due to 6 previous errors +error: aborting due to 3 previous errors diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.rs b/src/test/ui/type-alias-impl-trait/issue-60564.rs index fd254724fb554..4fc7679311a2e 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60564.rs +++ b/src/test/ui/type-alias-impl-trait/issue-60564.rs @@ -6,7 +6,6 @@ trait IterBits { } type IterBitsIter = impl std::iter::Iterator; -//~^ ERROR unconstrained opaque type impl IterBits for T where diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.stderr b/src/test/ui/type-alias-impl-trait/issue-60564.stderr index c5ac477187dd0..bbc93657be32f 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60564.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60564.stderr @@ -1,5 +1,5 @@ error: non-defining opaque type use in defining scope - --> $DIR/issue-60564.rs:21:9 + --> $DIR/issue-60564.rs:20:9 | LL | (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -10,13 +10,5 @@ note: used non-generic type `u8` for generic parameter LL | type IterBitsIter = impl std::iter::Iterator; | ^ -error: unconstrained opaque type - --> $DIR/issue-60564.rs:8:30 - | -LL | type IterBitsIter = impl std::iter::Iterator; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `IterBitsIter` must be used in combination with a concrete type within the same module - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs index 7f25d320677ed..5223fb1c702d6 100644 --- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs @@ -5,7 +5,7 @@ #![feature(type_alias_impl_trait)] trait Trait {} type Alias<'a, U> = impl Trait; -//~^ ERROR unconstrained opaque type + fn f<'a>() -> Alias<'a, ()> {} //~^ ERROR non-defining opaque type use in defining scope diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr index 4afa903969f26..7fb9a0c410e83 100644 --- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr @@ -10,13 +10,5 @@ note: used non-generic type `()` for generic parameter LL | type Alias<'a, U> = impl Trait; | ^ -error: unconstrained opaque type - --> $DIR/issue-68368-non-defining-use-2.rs:7:21 - | -LL | type Alias<'a, U> = impl Trait; - | ^^^^^^^^^^^^^ - | - = note: `Alias` must be used in combination with a concrete type within the same module - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs index b2b8a68bd7525..b50462bf237bb 100644 --- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs @@ -5,7 +5,7 @@ #![feature(type_alias_impl_trait)] trait Trait {} type Alias<'a, U> = impl Trait; -//~^ ERROR unconstrained opaque type + fn f<'a>() -> Alias<'a, ()> {} //~^ ERROR non-defining opaque type use in defining scope diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr index 94dc3b7c2b047..8059621b61a09 100644 --- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr @@ -10,13 +10,5 @@ note: used non-generic type `()` for generic parameter LL | type Alias<'a, U> = impl Trait; | ^ -error: unconstrained opaque type - --> $DIR/issue-68368-non-defining-use.rs:7:21 - | -LL | type Alias<'a, U> = impl Trait; - | ^^^^^^^^^^^^^ - | - = note: `Alias` must be used in combination with a concrete type within the same module - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs b/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs index cad3ff87749a6..5b332b8cb6bd8 100644 --- a/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs +++ b/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs @@ -7,11 +7,6 @@ fn main() {} type Two = impl Debug; //~^ ERROR `T` doesn't implement `Debug` -fn two(t: T) -> Two { - (t, 4i8) - //~^ ERROR non-defining opaque type use in defining scope -} - fn three(t: T) -> Two { (t, 5i8) } diff --git a/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr b/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr index aa05f62eb53ea..f946dc48a4bf9 100644 --- a/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr +++ b/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr @@ -1,23 +1,11 @@ -error: non-defining opaque type use in defining scope - --> $DIR/not_a_defining_use.rs:11:5 - | -LL | (t, 4i8) - | ^^^^^^^^ - | -note: used non-generic type `u32` for generic parameter - --> $DIR/not_a_defining_use.rs:7:13 - | -LL | type Two = impl Debug; - | ^ - error: concrete type differs from previous defining opaque type use - --> $DIR/not_a_defining_use.rs:29:1 + --> $DIR/not_a_defining_use.rs:24:1 | LL | fn four(t: T) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, i8)`, got `(T, ::Blub)` | note: previous use here - --> $DIR/not_a_defining_use.rs:15:1 + --> $DIR/not_a_defining_use.rs:10:1 | LL | fn three(t: T) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,6 +22,6 @@ help: consider restricting type parameter `T` LL | type Two = impl Debug; | +++++++++++++++++ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. From ee2158f1ee1e18076328891eb5f5cbfe5011c72a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 31 Jan 2022 16:44:26 +0000 Subject: [PATCH 41/53] run rustfmt --- compiler/rustc_infer/src/infer/opaque_types.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 0819c2363ffbc..e704ac6dc789a 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -554,13 +554,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ty_op: |ty| match *ty.kind() { // We can't normalize associated types from `rustc_infer`, // but we can eagerly register inference variables for them. - ty::Projection(projection_ty) if !projection_ty.has_escaping_bound_vars() => self.infer_projection( - param_env, - projection_ty, - cause.clone(), - 0, - &mut obligations, - ), + ty::Projection(projection_ty) if !projection_ty.has_escaping_bound_vars() => { + self.infer_projection( + param_env, + projection_ty, + cause.clone(), + 0, + &mut obligations, + ) + } // Replace all other mentions of the same opaque type with the hidden type, // as the bounds must hold on the hidden type after all. ty::Opaque(def_id2, substs2) if def_id == def_id2 && substs == substs2 => { From ebf2772c5892ec921d464bd56864266d0e7e9972 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 1 Feb 2022 14:43:46 +0000 Subject: [PATCH 42/53] Add regression test --- .../ui/type-alias-impl-trait/issue-93411.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/test/ui/type-alias-impl-trait/issue-93411.rs diff --git a/src/test/ui/type-alias-impl-trait/issue-93411.rs b/src/test/ui/type-alias-impl-trait/issue-93411.rs new file mode 100644 index 0000000000000..f0f2bcd7bb260 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-93411.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] + +// this test used to stack overflow due to infinite recursion. +// check-pass +// compile-flags: --edition=2018 + +use std::future::Future; + +fn main() { + let _ = move || async move { + let value = 0u8; + blah(&value).await; + }; +} + +type BlahFut<'a> = impl Future + Send + 'a; +fn blah<'a>(_value: &'a u8) -> BlahFut<'a> { + async {} +} \ No newline at end of file From 7a1ccf9a03cc0be995a7d8c8f3873c09e7d92f90 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 1 Feb 2022 15:09:06 +0000 Subject: [PATCH 43/53] Avoid an ICE in the presence of HKL --- .../src/region_infer/opaque_types.rs | 4 ++++ src/test/ui/impl-trait/issues/issue-88236.rs | 15 +++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 src/test/ui/impl-trait/issues/issue-88236.rs diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 139cebe0e43d8..f24d881639920 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -66,6 +66,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { let mut subst_regions = vec![self.universal_regions.fr_static]; let universal_substs = infcx.tcx.fold_regions(substs, &mut false, |region, _| { + if let ty::RePlaceholder(..) = region { + // Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs. + return region; + } let vid = self.to_region_vid(region); trace!(?vid); let scc = self.constraint_sccs.scc(vid); diff --git a/src/test/ui/impl-trait/issues/issue-88236.rs b/src/test/ui/impl-trait/issues/issue-88236.rs new file mode 100644 index 0000000000000..3bab46979ef37 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-88236.rs @@ -0,0 +1,15 @@ +// check-pass + +// this used to cause stack overflows + +trait Hrtb<'a> { + type Assoc; +} + +impl<'a> Hrtb<'a> for () { + type Assoc = (); +} + +fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} + +fn main() {} \ No newline at end of file From bae04fb3ded72c71a660d34749d83d2752580052 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 1 Feb 2022 16:41:32 +0000 Subject: [PATCH 44/53] Ensure we error in case of non-higher-kinded lifetimes --- .../ui/impl-trait/issues/issue-88236-2.rs | 23 +++++++++++++++++++ .../ui/impl-trait/issues/issue-88236-2.stderr | 20 ++++++++++++++++ src/test/ui/impl-trait/issues/issue-88236.rs | 6 ++++- .../ui/type-alias-impl-trait/issue-93411.rs | 2 +- 4 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/impl-trait/issues/issue-88236-2.rs create mode 100644 src/test/ui/impl-trait/issues/issue-88236-2.stderr diff --git a/src/test/ui/impl-trait/issues/issue-88236-2.rs b/src/test/ui/impl-trait/issues/issue-88236-2.rs new file mode 100644 index 0000000000000..f89ab7fbd364b --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-88236-2.rs @@ -0,0 +1,23 @@ +// this used to cause stack overflows + +trait Hrtb<'a> { + type Assoc; +} + +impl<'a> Hrtb<'a> for () { + type Assoc = (); +} + +impl<'a> Hrtb<'a> for &'a () { + type Assoc = (); +} + +fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} +fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { + &() //~ ERROR implementation of `Hrtb` is not general enough +} +fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { + x //~ ERROR implementation of `Hrtb` is not general enough +} + +fn main() {} diff --git a/src/test/ui/impl-trait/issues/issue-88236-2.stderr b/src/test/ui/impl-trait/issues/issue-88236-2.stderr new file mode 100644 index 0000000000000..95c4a52803698 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-88236-2.stderr @@ -0,0 +1,20 @@ +error: implementation of `Hrtb` is not general enough + --> $DIR/issue-88236-2.rs:17:5 + | +LL | &() + | ^^^ implementation of `Hrtb` is not general enough + | + = note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`... + = note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1` + +error: implementation of `Hrtb` is not general enough + --> $DIR/issue-88236-2.rs:20:5 + | +LL | x + | ^ implementation of `Hrtb` is not general enough + | + = note: `&()` must implement `Hrtb<'0>`, for any lifetime `'0`... + = note: ...but `Hrtb<'_>` is actually implemented for the type `&()` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/impl-trait/issues/issue-88236.rs b/src/test/ui/impl-trait/issues/issue-88236.rs index 3bab46979ef37..2ea35270a7e3b 100644 --- a/src/test/ui/impl-trait/issues/issue-88236.rs +++ b/src/test/ui/impl-trait/issues/issue-88236.rs @@ -10,6 +10,10 @@ impl<'a> Hrtb<'a> for () { type Assoc = (); } +impl<'a> Hrtb<'a> for &'a () { + type Assoc = (); +} + fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} -fn main() {} \ No newline at end of file +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-93411.rs b/src/test/ui/type-alias-impl-trait/issue-93411.rs index f0f2bcd7bb260..1f8c789267d1b 100644 --- a/src/test/ui/type-alias-impl-trait/issue-93411.rs +++ b/src/test/ui/type-alias-impl-trait/issue-93411.rs @@ -16,4 +16,4 @@ fn main() { type BlahFut<'a> = impl Future + Send + 'a; fn blah<'a>(_value: &'a u8) -> BlahFut<'a> { async {} -} \ No newline at end of file +} From 7f608eb9edb38ff271ff5be50dbbbb424cbf348f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 1 Feb 2022 17:28:46 +0000 Subject: [PATCH 45/53] Prevent two opaque types in their defining scopes from being defined via the other --- .../rustc_infer/src/infer/opaque_types.rs | 104 +++++++++++------- src/test/ui/impl-trait/example-calendar.rs | 3 +- .../ui/impl-trait/example-calendar.stderr | 19 ++++ src/test/ui/impl-trait/issues/issue-70877.rs | 4 +- .../ui/impl-trait/issues/issue-70877.stderr | 19 ++++ .../issues/issue-88236-2.nll.stderr | 39 +++++++ .../two_tait_defining_each_other.rs | 3 +- .../two_tait_defining_each_other.stderr | 19 ++++ .../two_tait_defining_each_other2.rs | 2 +- .../two_tait_defining_each_other2.stderr | 15 ++- .../two_tait_defining_each_other3.rs | 3 +- .../two_tait_defining_each_other3.stderr | 19 ++++ .../nested_type_alias_impl_trait.rs | 4 +- .../nested_type_alias_impl_trait.stderr | 19 ++++ 14 files changed, 216 insertions(+), 56 deletions(-) create mode 100644 src/test/ui/impl-trait/example-calendar.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-70877.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-88236-2.nll.stderr create mode 100644 src/test/ui/impl-trait/two_tait_defining_each_other.stderr create mode 100644 src/test/ui/impl-trait/two_tait_defining_each_other3.stderr create mode 100644 src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index e704ac6dc789a..35104c71bfc98 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -80,47 +80,69 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } if self.defining_use_anchor.is_some() { let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() { - ty::Opaque(def_id, substs) => Some(self.register_hidden_type( - OpaqueTypeKey { def_id, substs }, - cause.clone(), - param_env, - b, - // Check that this is `impl Trait` type is - // declared by `parent_def_id` -- i.e., one whose - // value we are inferring. At present, this is - // always true during the first phase of - // type-check, but not always true later on during - // NLL. Once we support named opaque types more fully, - // this same scenario will be able to arise during all phases. - // - // Here is an example using type alias `impl Trait` - // that indicates the distinction we are checking for: - // - // ```rust - // mod a { - // pub type Foo = impl Iterator; - // pub fn make_foo() -> Foo { .. } - // } - // - // mod b { - // fn foo() -> a::Foo { a::make_foo() } - // } - // ``` - // - // Here, the return type of `foo` references an - // `Opaque` indeed, but not one whose value is - // presently being inferred. You can get into a - // similar situation with closure return types - // today: - // - // ```rust - // fn foo() -> impl Iterator { .. } - // fn bar() { - // let x = || foo(); // returns the Opaque assoc with `foo` - // } - // ``` - self.opaque_type_origin(def_id, cause.span)?, - )), + ty::Opaque(def_id, substs) => { + if let ty::Opaque(did2, _) = *b.kind() { + if self.opaque_type_origin(did2, cause.span).is_some() { + self.tcx + .sess + .struct_span_err( + cause.span, + "opaque type's hidden type cannot be another opaque type from the same scope", + ) + .span_label(cause.span, "one of the two opaque types used here has to be outside its defining scope") + .span_note( + self.tcx.def_span(def_id), + "opaque type whose hidden type is being assigned", + ) + .span_note( + self.tcx.def_span(did2), + "opaque type being used as hidden type", + ) + .emit(); + } + } + Some(self.register_hidden_type( + OpaqueTypeKey { def_id, substs }, + cause.clone(), + param_env, + b, + // Check that this is `impl Trait` type is + // declared by `parent_def_id` -- i.e., one whose + // value we are inferring. At present, this is + // always true during the first phase of + // type-check, but not always true later on during + // NLL. Once we support named opaque types more fully, + // this same scenario will be able to arise during all phases. + // + // Here is an example using type alias `impl Trait` + // that indicates the distinction we are checking for: + // + // ```rust + // mod a { + // pub type Foo = impl Iterator; + // pub fn make_foo() -> Foo { .. } + // } + // + // mod b { + // fn foo() -> a::Foo { a::make_foo() } + // } + // ``` + // + // Here, the return type of `foo` references an + // `Opaque` indeed, but not one whose value is + // presently being inferred. You can get into a + // similar situation with closure return types + // today: + // + // ```rust + // fn foo() -> impl Iterator { .. } + // fn bar() { + // let x = || foo(); // returns the Opaque assoc with `foo` + // } + // ``` + self.opaque_type_origin(def_id, cause.span)?, + )) + } _ => None, }; if let Some(res) = process(a, b) { diff --git a/src/test/ui/impl-trait/example-calendar.rs b/src/test/ui/impl-trait/example-calendar.rs index 45dcb74a6e05c..26618eec1d712 100644 --- a/src/test/ui/impl-trait/example-calendar.rs +++ b/src/test/ui/impl-trait/example-calendar.rs @@ -1,4 +1,3 @@ -// run-pass // ignore-compare-mode-chalk #![feature(fn_traits, @@ -590,7 +589,7 @@ fn test_format_month() { fn format_months(it: impl Iterator) -> impl Iterator> { - it.map(format_month) + it.map(format_month) //~ ERROR opaque type's hidden type cannot be another opaque type } /// Takes an iterator of iterators of strings; the sub-iterators are consumed diff --git a/src/test/ui/impl-trait/example-calendar.stderr b/src/test/ui/impl-trait/example-calendar.stderr new file mode 100644 index 0000000000000..3894285947fec --- /dev/null +++ b/src/test/ui/impl-trait/example-calendar.stderr @@ -0,0 +1,19 @@ +error: opaque type's hidden type cannot be another opaque type from the same scope + --> $DIR/example-calendar.rs:592:5 + | +LL | it.map(format_month) + | ^^^^^^^^^^^^^^^^^^^^ one of the two opaque types used here has to be outside its defining scope + | +note: opaque type whose hidden type is being assigned + --> $DIR/example-calendar.rs:560:43 + | +LL | fn format_month(it: impl DateIterator) -> impl Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: opaque type being used as hidden type + --> $DIR/example-calendar.rs:590:39 + | +LL | -> impl Iterator> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/impl-trait/issues/issue-70877.rs b/src/test/ui/impl-trait/issues/issue-70877.rs index 42e5436390cbc..8169cfafac711 100644 --- a/src/test/ui/impl-trait/issues/issue-70877.rs +++ b/src/test/ui/impl-trait/issues/issue-70877.rs @@ -1,7 +1,5 @@ #![feature(type_alias_impl_trait)] -// check-pass - type FooArg<'a> = &'a dyn ToString; type FooRet = impl std::fmt::Debug; @@ -30,7 +28,7 @@ fn ham() -> Foo { fn oof() -> impl std::fmt::Debug { let mut bar = ham(); let func = bar.next().unwrap(); - return func(&"oof"); + return func(&"oof"); //~ ERROR opaque type's hidden type cannot be another opaque type } fn main() { diff --git a/src/test/ui/impl-trait/issues/issue-70877.stderr b/src/test/ui/impl-trait/issues/issue-70877.stderr new file mode 100644 index 0000000000000..8813bff3c353e --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-70877.stderr @@ -0,0 +1,19 @@ +error: opaque type's hidden type cannot be another opaque type from the same scope + --> $DIR/issue-70877.rs:31:12 + | +LL | return func(&"oof"); + | ^^^^^^^^^^^^ one of the two opaque types used here has to be outside its defining scope + | +note: opaque type whose hidden type is being assigned + --> $DIR/issue-70877.rs:28:13 + | +LL | fn oof() -> impl std::fmt::Debug { + | ^^^^^^^^^^^^^^^^^^^^ +note: opaque type being used as hidden type + --> $DIR/issue-70877.rs:4:15 + | +LL | type FooRet = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/impl-trait/issues/issue-88236-2.nll.stderr b/src/test/ui/impl-trait/issues/issue-88236-2.nll.stderr new file mode 100644 index 0000000000000..86323add77905 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-88236-2.nll.stderr @@ -0,0 +1,39 @@ +error: higher-ranked subtype error + --> $DIR/issue-88236-2.rs:17:5 + | +LL | &() + | ^^^ + +error: higher-ranked subtype error + --> $DIR/issue-88236-2.rs:17:5 + | +LL | &() + | ^^^ + +error: lifetime may not live long enough + --> $DIR/issue-88236-2.rs:20:5 + | +LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { + | -- lifetime `'b` defined here +LL | x + | ^ returning this value requires that `'b` must outlive `'static` + | +help: to allow this `impl Trait` to capture borrowed data with lifetime `'b`, add `'b` as a bound + | +LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> + 'b { + | ++++ + +error: higher-ranked subtype error + --> $DIR/issue-88236-2.rs:20:5 + | +LL | x + | ^ + +error: higher-ranked subtype error + --> $DIR/issue-88236-2.rs:20:5 + | +LL | x + | ^ + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other.rs b/src/test/ui/impl-trait/two_tait_defining_each_other.rs index eb8d24832eb43..6eb2a11b22c5f 100644 --- a/src/test/ui/impl-trait/two_tait_defining_each_other.rs +++ b/src/test/ui/impl-trait/two_tait_defining_each_other.rs @@ -1,7 +1,5 @@ #![feature(type_alias_impl_trait)] -// check-pass - type A = impl Foo; type B = impl Foo; @@ -12,6 +10,7 @@ fn muh(x: A) -> B { return Bar; // B's hidden type is Bar } x // A's hidden type is `Bar`, because all the hidden types of `B` are compared with each other + //~^ ERROR opaque type's hidden type cannot be another opaque type } struct Bar; diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other.stderr b/src/test/ui/impl-trait/two_tait_defining_each_other.stderr new file mode 100644 index 0000000000000..1a42ac525a6a8 --- /dev/null +++ b/src/test/ui/impl-trait/two_tait_defining_each_other.stderr @@ -0,0 +1,19 @@ +error: opaque type's hidden type cannot be another opaque type from the same scope + --> $DIR/two_tait_defining_each_other.rs:12:5 + | +LL | x // A's hidden type is `Bar`, because all the hidden types of `B` are compared with each other + | ^ one of the two opaque types used here has to be outside its defining scope + | +note: opaque type whose hidden type is being assigned + --> $DIR/two_tait_defining_each_other.rs:4:10 + | +LL | type B = impl Foo; + | ^^^^^^^^ +note: opaque type being used as hidden type + --> $DIR/two_tait_defining_each_other.rs:3:10 + | +LL | type A = impl Foo; + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other2.rs b/src/test/ui/impl-trait/two_tait_defining_each_other2.rs index 295e2375428aa..3b16d0f5e047f 100644 --- a/src/test/ui/impl-trait/two_tait_defining_each_other2.rs +++ b/src/test/ui/impl-trait/two_tait_defining_each_other2.rs @@ -1,13 +1,13 @@ #![feature(type_alias_impl_trait)] type A = impl Foo; -//~^ ERROR unconstrained opaque type type B = impl Foo; trait Foo {} fn muh(x: A) -> B { x // B's hidden type is A (opaquely) + //~^ ERROR opaque type's hidden type cannot be another opaque type } struct Bar; diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other2.stderr b/src/test/ui/impl-trait/two_tait_defining_each_other2.stderr index e48a5724a7fa5..ef2089a6c5b17 100644 --- a/src/test/ui/impl-trait/two_tait_defining_each_other2.stderr +++ b/src/test/ui/impl-trait/two_tait_defining_each_other2.stderr @@ -1,10 +1,19 @@ -error: unconstrained opaque type +error: opaque type's hidden type cannot be another opaque type from the same scope + --> $DIR/two_tait_defining_each_other2.rs:9:5 + | +LL | x // B's hidden type is A (opaquely) + | ^ one of the two opaque types used here has to be outside its defining scope + | +note: opaque type whose hidden type is being assigned + --> $DIR/two_tait_defining_each_other2.rs:4:10 + | +LL | type B = impl Foo; + | ^^^^^^^^ +note: opaque type being used as hidden type --> $DIR/two_tait_defining_each_other2.rs:3:10 | LL | type A = impl Foo; | ^^^^^^^^ - | - = note: `A` must be used in combination with a concrete type within the same module error: aborting due to previous error diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other3.rs b/src/test/ui/impl-trait/two_tait_defining_each_other3.rs index c289b43c4259f..37f8ae1b84b55 100644 --- a/src/test/ui/impl-trait/two_tait_defining_each_other3.rs +++ b/src/test/ui/impl-trait/two_tait_defining_each_other3.rs @@ -1,7 +1,5 @@ #![feature(type_alias_impl_trait)] -// check-pass - type A = impl Foo; type B = impl Foo; @@ -10,6 +8,7 @@ trait Foo {} fn muh(x: A) -> B { if false { return x; // B's hidden type is A (opaquely) + //~^ ERROR opaque type's hidden type cannot be another opaque type } Bar // A's hidden type is `Bar`, because all the return types are compared with each other } diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other3.stderr b/src/test/ui/impl-trait/two_tait_defining_each_other3.stderr new file mode 100644 index 0000000000000..b06dc16d5e700 --- /dev/null +++ b/src/test/ui/impl-trait/two_tait_defining_each_other3.stderr @@ -0,0 +1,19 @@ +error: opaque type's hidden type cannot be another opaque type from the same scope + --> $DIR/two_tait_defining_each_other3.rs:10:16 + | +LL | return x; // B's hidden type is A (opaquely) + | ^ one of the two opaque types used here has to be outside its defining scope + | +note: opaque type whose hidden type is being assigned + --> $DIR/two_tait_defining_each_other3.rs:4:10 + | +LL | type B = impl Foo; + | ^^^^^^^^ +note: opaque type being used as hidden type + --> $DIR/two_tait_defining_each_other3.rs:3:10 + | +LL | type A = impl Foo; + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs b/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs index 6282264d8fee5..60b6e1aac6281 100644 --- a/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs +++ b/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs @@ -1,5 +1,5 @@ #![feature(type_alias_impl_trait)] -// build-pass (FIXME(62277): could be check-pass?) + mod my_mod { use std::fmt::Debug; @@ -11,7 +11,7 @@ mod my_mod { } pub fn get_foot() -> Foot { - get_foo() + get_foo() //~ ERROR opaque type's hidden type cannot be another opaque type } } diff --git a/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr b/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr new file mode 100644 index 0000000000000..fa6ecf68d28f3 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr @@ -0,0 +1,19 @@ +error: opaque type's hidden type cannot be another opaque type from the same scope + --> $DIR/nested_type_alias_impl_trait.rs:14:9 + | +LL | get_foo() + | ^^^^^^^^^ one of the two opaque types used here has to be outside its defining scope + | +note: opaque type whose hidden type is being assigned + --> $DIR/nested_type_alias_impl_trait.rs:7:21 + | +LL | pub type Foot = impl Debug; + | ^^^^^^^^^^ +note: opaque type being used as hidden type + --> $DIR/nested_type_alias_impl_trait.rs:6:20 + | +LL | pub type Foo = impl Debug; + | ^^^^^^^^^^ + +error: aborting due to previous error + From be153f0976705f8d7ca45540a4965bb156b2cc34 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 2 Feb 2022 15:03:44 +0000 Subject: [PATCH 46/53] Only prevent TAITs from defining each other, RPIT and async are fine, they only ever have one defining site, and it is ordered correctly around expected and actual type in type comparisons --- .../rustc_infer/src/infer/opaque_types.rs | 9 ++++++++- src/test/ui/impl-trait/example-calendar.rs | 3 ++- .../ui/impl-trait/example-calendar.stderr | 19 ------------------- 3 files changed, 10 insertions(+), 21 deletions(-) delete mode 100644 src/test/ui/impl-trait/example-calendar.stderr diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 35104c71bfc98..46420fbe0c305 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -82,7 +82,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() { ty::Opaque(def_id, substs) => { if let ty::Opaque(did2, _) = *b.kind() { - if self.opaque_type_origin(did2, cause.span).is_some() { + // We could accept this, but there are various ways to handle this situation, and we don't + // want to make a decision on it right now. Likely this case is so super rare anyway, that + // no one encounters it in practice. + // It does occur however in `fn fut() -> impl Future { async { 42 } }`, + // where it is of no concern, so we only check for TAITs. + if let Some(OpaqueTyOrigin::TyAlias) = + self.opaque_type_origin(did2, cause.span) + { self.tcx .sess .struct_span_err( diff --git a/src/test/ui/impl-trait/example-calendar.rs b/src/test/ui/impl-trait/example-calendar.rs index 26618eec1d712..45dcb74a6e05c 100644 --- a/src/test/ui/impl-trait/example-calendar.rs +++ b/src/test/ui/impl-trait/example-calendar.rs @@ -1,3 +1,4 @@ +// run-pass // ignore-compare-mode-chalk #![feature(fn_traits, @@ -589,7 +590,7 @@ fn test_format_month() { fn format_months(it: impl Iterator) -> impl Iterator> { - it.map(format_month) //~ ERROR opaque type's hidden type cannot be another opaque type + it.map(format_month) } /// Takes an iterator of iterators of strings; the sub-iterators are consumed diff --git a/src/test/ui/impl-trait/example-calendar.stderr b/src/test/ui/impl-trait/example-calendar.stderr deleted file mode 100644 index 3894285947fec..0000000000000 --- a/src/test/ui/impl-trait/example-calendar.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error: opaque type's hidden type cannot be another opaque type from the same scope - --> $DIR/example-calendar.rs:592:5 - | -LL | it.map(format_month) - | ^^^^^^^^^^^^^^^^^^^^ one of the two opaque types used here has to be outside its defining scope - | -note: opaque type whose hidden type is being assigned - --> $DIR/example-calendar.rs:560:43 - | -LL | fn format_month(it: impl DateIterator) -> impl Iterator { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: opaque type being used as hidden type - --> $DIR/example-calendar.rs:590:39 - | -LL | -> impl Iterator> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - From d9bb93f3a40871e54d8d1cecd239af9b0d96c7d5 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 2 Feb 2022 17:15:18 +0000 Subject: [PATCH 47/53] Fix some doctests where the main function returns an opaque type --- compiler/rustc_trait_selection/src/traits/codegen.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs index 759bc69698167..04a7da06063ba 100644 --- a/compiler/rustc_trait_selection/src/traits/codegen.rs +++ b/compiler/rustc_trait_selection/src/traits/codegen.rs @@ -90,6 +90,11 @@ pub fn codegen_fulfill_obligation<'tcx>( }); let impl_source = drain_fulfillment_cx_or_panic(&infcx, &mut fulfill_cx, impl_source); + // We may constrain the hidden types of opaque types in this query, but this is + // not information our callers need, as all that information is handled by borrowck + // and typeck. + drop(infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types()); + debug!("Cache miss: {:?} => {:?}", trait_ref, impl_source); Ok(impl_source) }) From d526a8d5940182c9e020783600578a1f7b4b2122 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 3 Feb 2022 13:44:29 +0000 Subject: [PATCH 48/53] Clean up opaque type obligations in query results --- .../src/infer/canonical/query_response.rs | 15 +++++++-------- compiler/rustc_middle/src/infer/canonical.rs | 11 +++++++---- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 18a1120051efe..7d86f8a763c30 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -25,7 +25,7 @@ use rustc_middle::arena::ArenaAllocatable; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; -use rustc_middle::ty::{self, BoundVar, Const, OpaqueTypeKey, ToPredicate, Ty, TyCtxt}; +use rustc_middle::ty::{self, BoundVar, Const, ToPredicate, Ty, TyCtxt}; use rustc_span::Span; use std::fmt::Debug; use std::iter; @@ -146,13 +146,13 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { }) } - fn take_opaque_types_for_query_response(&self) -> Vec<(OpaqueTypeKey<'tcx>, Ty<'tcx>)> { + fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> { self.inner .borrow_mut() .opaque_type_storage .take_opaque_types() .into_iter() - .map(|(k, v)| (k, v.hidden_type.ty)) + .map(|(k, v)| (self.tcx.mk_opaque(k.def_id, k.substs), v.hidden_type.ty)) .collect() } @@ -497,11 +497,10 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let mut obligations = vec![]; // Carry all newly resolved opaque types to the caller's scope - for &(key, ty) in &query_response.value.opaque_types { - let substs = substitute_value(self.tcx, &result_subst, key.substs); - let opaque = self.tcx.mk_opaque(key.def_id, substs); - let ty = substitute_value(self.tcx, &result_subst, ty); - obligations.extend(self.handle_opaque_type(opaque, ty, cause, param_env)?.obligations); + for &(a, b) in &query_response.value.opaque_types { + let a = substitute_value(self.tcx, &result_subst, a); + let b = substitute_value(self.tcx, &result_subst, b); + obligations.extend(self.handle_opaque_type(a, b, cause, param_env)?.obligations); } Ok(InferOk { value: result_subst, obligations }) diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 654ec022b604f..2fc901bdbff34 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -23,7 +23,7 @@ use crate::infer::MemberConstraint; use crate::ty::subst::GenericArg; -use crate::ty::{self, BoundVar, List, OpaqueTypeKey, Region, Ty, TyCtxt}; +use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt}; use rustc_index::vec::IndexVec; use rustc_macros::HashStable; use smallvec::SmallVec; @@ -178,9 +178,12 @@ pub struct QueryResponse<'tcx, R> { pub var_values: CanonicalVarValues<'tcx>, pub region_constraints: QueryRegionConstraints<'tcx>, pub certainty: Certainty, - /// List of opaque types for which we figured out a hidden type - /// during the evaluation of the query. - pub opaque_types: Vec<(OpaqueTypeKey<'tcx>, Ty<'tcx>)>, + /// List of opaque types which we tried to compare to another type. + /// Inside the query we don't know yet whether the opaque type actually + /// should get its hidden type inferred. So we bubble the opaque type + /// and the type it was compared against upwards and let the query caller + /// handle it. + pub opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>, pub value: R, } From 80c7b6108fc89765d812c39c2c6d1df1a9dd2b5f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 3 Feb 2022 14:48:05 +0000 Subject: [PATCH 49/53] Add tests for lifetime-swaps, not just type param swaps --- .../multiple-def-uses-in-one-fn-lifetimes.rs | 10 ++++++++++ .../multiple-def-uses-in-one-fn-lifetimes.stderr | 14 ++++++++++++++ .../multiple-def-uses-in-one-fn-pass.rs | 9 +++++++++ 3 files changed, 33 insertions(+) create mode 100644 src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs create mode 100644 src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs new file mode 100644 index 0000000000000..b144b267fbbc3 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs @@ -0,0 +1,10 @@ + +#![feature(type_alias_impl_trait)] + +type Foo<'a, 'b> = impl std::fmt::Debug; + +fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) { + (i, i) //~^ ERROR concrete type differs from previous +} + +fn main() {} \ No newline at end of file diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr new file mode 100644 index 0000000000000..2499d3cbca62e --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr @@ -0,0 +1,14 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:1 + | +LL | fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&'a i32`, got `&'b i32` + | +note: previous use here + --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:1 + | +LL | fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs index f412b2d0e7db7..83fd9a1da450b 100644 --- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs @@ -7,6 +7,15 @@ fn f(a: A, b: B) -> (X, X) (a.clone(), a) } +type Foo<'a, 'b> = impl std::fmt::Debug; + +fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) { + (i, j) +} + fn main() { println!("{}", as ToString>::to_string(&f(42_i32, String::new()).1)); + let meh = 42; + let muh = 69; + println!("{:?}", foo(&meh, &muh)); } From 6807d3773dad925cab3797aef7e7e5a50bfabfef Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 3 Feb 2022 15:11:45 +0000 Subject: [PATCH 50/53] Add some new tests with amusing diagnostics --- .../multiple-def-uses-in-one-fn-lifetimes.rs | 3 +-- ...multiple-def-uses-in-one-fn-lifetimes.stderr | 4 ++-- src/test/ui/type-alias-impl-trait/nested.rs | 17 +++++++++++++++++ src/test/ui/type-alias-impl-trait/nested.stderr | 12 ++++++++++++ .../type-alias-impl-trait/self-referential-2.rs | 10 ++++++++++ .../self-referential-2.stderr | 11 +++++++++++ .../type-alias-impl-trait/self-referential-3.rs | 14 ++++++++++++++ .../type-alias-impl-trait/self-referential.rs | 13 +++++++++++++ .../self-referential.stderr | 11 +++++++++++ 9 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/type-alias-impl-trait/nested.rs create mode 100644 src/test/ui/type-alias-impl-trait/nested.stderr create mode 100644 src/test/ui/type-alias-impl-trait/self-referential-2.rs create mode 100644 src/test/ui/type-alias-impl-trait/self-referential-2.stderr create mode 100644 src/test/ui/type-alias-impl-trait/self-referential-3.rs create mode 100644 src/test/ui/type-alias-impl-trait/self-referential.rs create mode 100644 src/test/ui/type-alias-impl-trait/self-referential.stderr diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs index b144b267fbbc3..f39bf4aeb29ae 100644 --- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs @@ -1,4 +1,3 @@ - #![feature(type_alias_impl_trait)] type Foo<'a, 'b> = impl std::fmt::Debug; @@ -7,4 +6,4 @@ fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) { (i, i) //~^ ERROR concrete type differs from previous } -fn main() {} \ No newline at end of file +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr index 2499d3cbca62e..49d08dda9f994 100644 --- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr @@ -1,11 +1,11 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:1 + --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:5:1 | LL | fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&'a i32`, got `&'b i32` | note: previous use here - --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:1 + --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:5:1 | LL | fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/type-alias-impl-trait/nested.rs b/src/test/ui/type-alias-impl-trait/nested.rs new file mode 100644 index 0000000000000..4cdfbf0804106 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/nested.rs @@ -0,0 +1,17 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl std::fmt::Debug; +type Bar = impl Trait; + +trait Trait {} + +impl Trait for U {} + +fn bar() -> Bar { + 42 +} + +fn main() { + println!("{:?}", bar()); + //~^ ERROR `impl Trait` doesn't implement `Debug` +} diff --git a/src/test/ui/type-alias-impl-trait/nested.stderr b/src/test/ui/type-alias-impl-trait/nested.stderr new file mode 100644 index 0000000000000..43bdd73454b28 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/nested.stderr @@ -0,0 +1,12 @@ +error[E0277]: `impl Trait` doesn't implement `Debug` + --> $DIR/nested.rs:15:22 + | +LL | println!("{:?}", bar()); + | ^^^^^ `impl Trait` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = help: the trait `Debug` is not implemented for `impl Trait` + = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/self-referential-2.rs b/src/test/ui/type-alias-impl-trait/self-referential-2.rs new file mode 100644 index 0000000000000..e9ace992c8b9d --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/self-referential-2.rs @@ -0,0 +1,10 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl std::fmt::Debug; +type Bar = impl PartialEq; + +fn bar() -> Bar { + 42_i32 //~ ERROR can't compare `i32` with `impl Debug` +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/self-referential-2.stderr b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr new file mode 100644 index 0000000000000..2c3630dc39425 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr @@ -0,0 +1,11 @@ +error[E0277]: can't compare `i32` with `impl Debug` + --> $DIR/self-referential-2.rs:7:5 + | +LL | 42_i32 + | ^^^^^^ no implementation for `i32 == impl Debug` + | + = help: the trait `PartialEq` is not implemented for `i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/self-referential-3.rs b/src/test/ui/type-alias-impl-trait/self-referential-3.rs new file mode 100644 index 0000000000000..d40715717d49d --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/self-referential-3.rs @@ -0,0 +1,14 @@ +// run-pass +#![feature(type_alias_impl_trait)] + +type Bar<'a, 'b> = impl PartialEq> + std::fmt::Debug; + +fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { + i +} + +fn main() { + let meh = 42; + let muh = 42; + assert_eq!(bar(&meh), bar(&muh)); +} diff --git a/src/test/ui/type-alias-impl-trait/self-referential.rs b/src/test/ui/type-alias-impl-trait/self-referential.rs new file mode 100644 index 0000000000000..d5085b9419e8e --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/self-referential.rs @@ -0,0 +1,13 @@ +#![feature(type_alias_impl_trait)] + +type Bar<'a, 'b> = impl PartialEq> + std::fmt::Debug; + +fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { + i //~ ERROR can't compare `&i32` with `impl PartialEq + Debug` + --> $DIR/self-referential.rs:6:5 + | +LL | i + | ^ no implementation for `&i32 == impl PartialEq + Debug` + | + = help: the trait `PartialEq + Debug>` is not implemented for `&i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 75461633350a24c3c23d387155c200ae31ccc870 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 3 Feb 2022 15:53:23 +0000 Subject: [PATCH 51/53] Improve self-referential diagnostic somewhat --- compiler/rustc_middle/src/ty/print/pretty.rs | 31 ++++++++++++------- src/test/ui/type-alias-impl-trait/nested.rs | 2 +- .../ui/type-alias-impl-trait/nested.stderr | 6 ++-- .../type-alias-impl-trait/self-referential.rs | 2 +- .../self-referential.stderr | 6 ++-- 5 files changed, 27 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 62a0143817a9c..11a3ee5362967 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -644,20 +644,18 @@ pub trait PrettyPrinter<'tcx>: return Ok(self); } - return with_no_queries(|| { - let def_key = self.tcx().def_key(def_id); - if let Some(name) = def_key.disambiguated_data.data.get_opt_name() { - p!(write("{}", name)); - // FIXME(eddyb) print this with `print_def_path`. - if !substs.is_empty() { - p!("::"); - p!(generic_delimiters(|cx| cx.comma_sep(substs.iter()))); - } - return Ok(self); + let def_key = self.tcx().def_key(def_id); + if let Some(name) = def_key.disambiguated_data.data.get_opt_name() { + p!(write("{}", name)); + // FIXME(eddyb) print this with `print_def_path`. + if !substs.is_empty() { + p!("::"); + p!(generic_delimiters(|cx| cx.comma_sep(substs.iter()))); } + return Ok(self); + } - self.pretty_print_opaque_impl_type(def_id, substs) - }); + return self.pretty_print_opaque_impl_type(def_id, substs); } ty::Str => p!("str"), ty::Generator(did, substs, movability) => { @@ -900,6 +898,15 @@ pub trait PrettyPrinter<'tcx>: if !first { p!(", "); } + if let GenericArgKind::Type(ty) = ty.unpack() { + if let ty::Opaque(d, substs) = *ty.kind() { + if d == def_id { + p!(print_def_path(d, substs)); + first = false; + continue; + } + } + } p!(print(trait_ref.rebind(*ty))); first = false; } diff --git a/src/test/ui/type-alias-impl-trait/nested.rs b/src/test/ui/type-alias-impl-trait/nested.rs index 4cdfbf0804106..e55fe3a3aafe7 100644 --- a/src/test/ui/type-alias-impl-trait/nested.rs +++ b/src/test/ui/type-alias-impl-trait/nested.rs @@ -13,5 +13,5 @@ fn bar() -> Bar { fn main() { println!("{:?}", bar()); - //~^ ERROR `impl Trait` doesn't implement `Debug` + //~^ ERROR `impl Trait` doesn't implement `Debug` } diff --git a/src/test/ui/type-alias-impl-trait/nested.stderr b/src/test/ui/type-alias-impl-trait/nested.stderr index 43bdd73454b28..eff56e3b76d9c 100644 --- a/src/test/ui/type-alias-impl-trait/nested.stderr +++ b/src/test/ui/type-alias-impl-trait/nested.stderr @@ -1,10 +1,10 @@ -error[E0277]: `impl Trait` doesn't implement `Debug` +error[E0277]: `impl Trait` doesn't implement `Debug` --> $DIR/nested.rs:15:22 | LL | println!("{:?}", bar()); - | ^^^^^ `impl Trait` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^ `impl Trait` cannot be formatted using `{:?}` because it doesn't implement `Debug` | - = help: the trait `Debug` is not implemented for `impl Trait` + = help: the trait `Debug` is not implemented for `impl Trait` = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/self-referential.rs b/src/test/ui/type-alias-impl-trait/self-referential.rs index d5085b9419e8e..46468bc98b968 100644 --- a/src/test/ui/type-alias-impl-trait/self-referential.rs +++ b/src/test/ui/type-alias-impl-trait/self-referential.rs @@ -3,7 +3,7 @@ type Bar<'a, 'b> = impl PartialEq> + std::fmt::Debug; fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { - i //~ ERROR can't compare `&i32` with `impl PartialEq } fn main() { diff --git a/src/test/ui/type-alias-impl-trait/self-referential.stderr b/src/test/ui/type-alias-impl-trait/self-referential.stderr index 8bc2cb9b05cd1..29f1e0bec083d 100644 --- a/src/test/ui/type-alias-impl-trait/self-referential.stderr +++ b/src/test/ui/type-alias-impl-trait/self-referential.stderr @@ -1,10 +1,10 @@ -error[E0277]: can't compare `&i32` with `impl PartialEq + Debug` +error[E0277]: can't compare `&i32` with `impl PartialEq::{opaque#0}> + Debug` --> $DIR/self-referential.rs:6:5 | LL | i - | ^ no implementation for `&i32 == impl PartialEq + Debug` + | ^ no implementation for `&i32 == impl PartialEq::{opaque#0}> + Debug` | - = help: the trait `PartialEq + Debug>` is not implemented for `&i32` + = help: the trait `PartialEq::{opaque#0}> + Debug>` is not implemented for `&i32` error: aborting due to previous error From c93f571c2a040a29525b077e557b3d592072fcf2 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 7 Feb 2022 15:50:42 +0000 Subject: [PATCH 52/53] Print opaque types from type aliases via their path --- compiler/rustc_middle/src/ty/print/pretty.rs | 34 ++++++++----------- .../assoc-type-eq-with-dyn-atb-fail.stderr | 2 +- src/test/ui/impl-trait/auto-trait.rs | 2 +- src/test/ui/impl-trait/auto-trait.stderr | 4 +-- src/test/ui/impl-trait/negative-reasoning.rs | 2 +- .../ui/impl-trait/negative-reasoning.stderr | 6 ++-- src/test/ui/lint/lint-ctypes-73249-2.rs | 2 +- src/test/ui/lint/lint-ctypes-73249-2.stderr | 2 +- src/test/ui/lint/lint-ctypes-73249-3.rs | 2 +- src/test/ui/lint/lint-ctypes-73249-3.stderr | 2 +- src/test/ui/lint/lint-ctypes-73249-5.rs | 2 +- src/test/ui/lint/lint-ctypes-73249-5.stderr | 2 +- src/test/ui/lint/lint-ctypes-73251-1.rs | 2 +- src/test/ui/lint/lint-ctypes-73251-1.stderr | 2 +- src/test/ui/lint/lint-ctypes-73251-2.rs | 2 +- src/test/ui/lint/lint-ctypes-73251-2.stderr | 2 +- src/test/ui/lint/opaque-ty-ffi-unsafe.rs | 2 +- src/test/ui/lint/opaque-ty-ffi-unsafe.stderr | 2 +- src/test/ui/traits/alias/issue-83613.rs | 2 +- src/test/ui/traits/alias/issue-83613.stderr | 4 +-- .../auto-trait-leakage2.stderr | 6 ++-- .../declared_but_not_defined_in_scope.stderr | 2 +- .../type-alias-impl-trait/issue-63279.stderr | 2 +- .../type-alias-impl-trait/issue-74280.stderr | 2 +- .../type-alias-impl-trait/issue-77179.stderr | 2 +- .../multiple-def-uses-in-one-fn3.stderr | 2 +- .../nested-tait-inference.rs | 2 +- .../nested-tait-inference.stderr | 4 +-- .../nested-tait-inference2.rs | 2 +- .../nested-tait-inference2.stderr | 4 +-- src/test/ui/type-alias-impl-trait/nested.rs | 2 +- .../ui/type-alias-impl-trait/nested.stderr | 6 ++-- ...o_revealing_outside_defining_module.stderr | 4 +-- .../self-referential-2.rs | 2 +- .../self-referential-2.stderr | 6 ++-- .../self-referential-4.rs | 25 ++++++++++++++ .../self-referential-4.stderr | 27 +++++++++++++++ .../type-alias-impl-trait/self-referential.rs | 14 +++++++- .../self-referential.stderr | 24 ++++++++++--- .../structural-match-no-leak.rs | 2 +- .../structural-match-no-leak.stderr | 2 +- .../type-alias-impl-trait/structural-match.rs | 2 +- .../structural-match.stderr | 2 +- .../type_of_a_let.stderr | 4 +-- 44 files changed, 153 insertions(+), 77 deletions(-) create mode 100644 src/test/ui/type-alias-impl-trait/self-referential-4.rs create mode 100644 src/test/ui/type-alias-impl-trait/self-referential-4.stderr diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 11a3ee5362967..6521957ec944c 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -644,18 +644,23 @@ pub trait PrettyPrinter<'tcx>: return Ok(self); } - let def_key = self.tcx().def_key(def_id); - if let Some(name) = def_key.disambiguated_data.data.get_opt_name() { - p!(write("{}", name)); - // FIXME(eddyb) print this with `print_def_path`. - if !substs.is_empty() { - p!("::"); - p!(generic_delimiters(|cx| cx.comma_sep(substs.iter()))); + let parent = self.tcx().parent(def_id).expect("opaque types always have a parent"); + match self.tcx().def_kind(parent) { + DefKind::TyAlias | DefKind::AssocTy => { + if let ty::Opaque(d, _) = *self.tcx().type_of(parent).kind() { + if d == def_id { + // If the type alias directly starts with the `impl` of the + // opaque type we're printing, then skip the `::{opaque#1}`. + p!(print_def_path(parent, substs)); + return Ok(self); + } + } + // Complex opaque type, e.g. `type Foo = (i32, impl Debug);` + p!(print_def_path(def_id, substs)); + return Ok(self); } - return Ok(self); + _ => return self.pretty_print_opaque_impl_type(def_id, substs), } - - return self.pretty_print_opaque_impl_type(def_id, substs); } ty::Str => p!("str"), ty::Generator(did, substs, movability) => { @@ -898,15 +903,6 @@ pub trait PrettyPrinter<'tcx>: if !first { p!(", "); } - if let GenericArgKind::Type(ty) = ty.unpack() { - if let ty::Opaque(d, substs) = *ty.kind() { - if d == def_id { - p!(print_def_path(d, substs)); - first = false; - continue; - } - } - } p!(print(trait_ref.rebind(*ty))); first = false; } 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 be4bfa6272b8d..f1dcd34066dbc 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 @@ -4,7 +4,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied LL | Box::new(AssocNoCopy) | ^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` | - = note: required for the cast to the object type `dyn Bar` + = note: required for the cast to the object type `dyn Bar::Out::{opaque#0}>` error: aborting due to previous error diff --git a/src/test/ui/impl-trait/auto-trait.rs b/src/test/ui/impl-trait/auto-trait.rs index cf2773f4ef59d..35994e4a5ba3f 100644 --- a/src/test/ui/impl-trait/auto-trait.rs +++ b/src/test/ui/impl-trait/auto-trait.rs @@ -19,7 +19,7 @@ impl AnotherTrait for T {} // (We treat opaque types as "foreign types" that could grow more impls // in the future.) impl AnotherTrait for D { - //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D` + //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D` } fn main() {} diff --git a/src/test/ui/impl-trait/auto-trait.stderr b/src/test/ui/impl-trait/auto-trait.stderr index 26cd8fb6a9b5c..81009413c9a26 100644 --- a/src/test/ui/impl-trait/auto-trait.stderr +++ b/src/test/ui/impl-trait/auto-trait.stderr @@ -1,11 +1,11 @@ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D` +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D` --> $DIR/auto-trait.rs:21:1 | LL | impl AnotherTrait for T {} | -------------------------------- first implementation here ... LL | impl AnotherTrait for D { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` error: aborting due to previous error diff --git a/src/test/ui/impl-trait/negative-reasoning.rs b/src/test/ui/impl-trait/negative-reasoning.rs index d173fe83fb791..70e24a3a9d029 100644 --- a/src/test/ui/impl-trait/negative-reasoning.rs +++ b/src/test/ui/impl-trait/negative-reasoning.rs @@ -17,7 +17,7 @@ impl AnotherTrait for T {} // This is in error, because we cannot assume that `OpaqueType: !Debug` impl AnotherTrait for D { - //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D` + //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D` } fn main() {} diff --git a/src/test/ui/impl-trait/negative-reasoning.stderr b/src/test/ui/impl-trait/negative-reasoning.stderr index e39a8e53f7985..6b8cc9e737423 100644 --- a/src/test/ui/impl-trait/negative-reasoning.stderr +++ b/src/test/ui/impl-trait/negative-reasoning.stderr @@ -1,13 +1,13 @@ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D` +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D` --> $DIR/negative-reasoning.rs:19:1 | LL | impl AnotherTrait for T {} | ------------------------------------------- first implementation here ... LL | impl AnotherTrait for D { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` | - = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `impl OpaqueTrait` in future versions + = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `OpaqueType` in future versions error: aborting due to previous error diff --git a/src/test/ui/lint/lint-ctypes-73249-2.rs b/src/test/ui/lint/lint-ctypes-73249-2.rs index fe578f51b63a0..691047c8a405b 100644 --- a/src/test/ui/lint/lint-ctypes-73249-2.rs +++ b/src/test/ui/lint/lint-ctypes-73249-2.rs @@ -23,7 +23,7 @@ pub struct A { } extern "C" { - pub fn lint_me() -> A<()>; //~ ERROR: uses type `impl Baz` + pub fn lint_me() -> A<()>; //~ ERROR: uses type `Qux` } fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73249-2.stderr b/src/test/ui/lint/lint-ctypes-73249-2.stderr index 36dbe3217d75a..7c85e9fa85c63 100644 --- a/src/test/ui/lint/lint-ctypes-73249-2.stderr +++ b/src/test/ui/lint/lint-ctypes-73249-2.stderr @@ -1,4 +1,4 @@ -error: `extern` block uses type `impl Baz`, which is not FFI-safe +error: `extern` block uses type `Qux`, which is not FFI-safe --> $DIR/lint-ctypes-73249-2.rs:26:25 | LL | pub fn lint_me() -> A<()>; diff --git a/src/test/ui/lint/lint-ctypes-73249-3.rs b/src/test/ui/lint/lint-ctypes-73249-3.rs index ec12de00739e4..ef8ab7e03d2f0 100644 --- a/src/test/ui/lint/lint-ctypes-73249-3.rs +++ b/src/test/ui/lint/lint-ctypes-73249-3.rs @@ -17,7 +17,7 @@ pub struct A { } extern "C" { - pub fn lint_me() -> A; //~ ERROR: uses type `impl Baz` + pub fn lint_me() -> A; //~ ERROR: uses type `Qux` } fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73249-3.stderr b/src/test/ui/lint/lint-ctypes-73249-3.stderr index e987ec90228c1..83e2a233c4335 100644 --- a/src/test/ui/lint/lint-ctypes-73249-3.stderr +++ b/src/test/ui/lint/lint-ctypes-73249-3.stderr @@ -1,4 +1,4 @@ -error: `extern` block uses type `impl Baz`, which is not FFI-safe +error: `extern` block uses type `Qux`, which is not FFI-safe --> $DIR/lint-ctypes-73249-3.rs:20:25 | LL | pub fn lint_me() -> A; diff --git a/src/test/ui/lint/lint-ctypes-73249-5.rs b/src/test/ui/lint/lint-ctypes-73249-5.rs index 58c2d7a501ad5..083fb6c5fb16d 100644 --- a/src/test/ui/lint/lint-ctypes-73249-5.rs +++ b/src/test/ui/lint/lint-ctypes-73249-5.rs @@ -17,7 +17,7 @@ pub struct A { } extern "C" { - pub fn lint_me() -> A; //~ ERROR: uses type `impl Baz` + pub fn lint_me() -> A; //~ ERROR: uses type `Qux` } fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73249-5.stderr b/src/test/ui/lint/lint-ctypes-73249-5.stderr index 749714c7df8d7..37781d78cf28c 100644 --- a/src/test/ui/lint/lint-ctypes-73249-5.stderr +++ b/src/test/ui/lint/lint-ctypes-73249-5.stderr @@ -1,4 +1,4 @@ -error: `extern` block uses type `impl Baz`, which is not FFI-safe +error: `extern` block uses type `Qux`, which is not FFI-safe --> $DIR/lint-ctypes-73249-5.rs:20:25 | LL | pub fn lint_me() -> A; diff --git a/src/test/ui/lint/lint-ctypes-73251-1.rs b/src/test/ui/lint/lint-ctypes-73251-1.rs index dc4c7efd7ef23..145ba784f7c66 100644 --- a/src/test/ui/lint/lint-ctypes-73251-1.rs +++ b/src/test/ui/lint/lint-ctypes-73251-1.rs @@ -20,7 +20,7 @@ fn assign() -> Qux { } extern "C" { - pub fn lint_me() -> ::Assoc; //~ ERROR: uses type `impl Baz` + pub fn lint_me() -> ::Assoc; //~ ERROR: uses type `Qux` } fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73251-1.stderr b/src/test/ui/lint/lint-ctypes-73251-1.stderr index 505ccd5a930ce..76b19d37e21a6 100644 --- a/src/test/ui/lint/lint-ctypes-73251-1.stderr +++ b/src/test/ui/lint/lint-ctypes-73251-1.stderr @@ -1,4 +1,4 @@ -error: `extern` block uses type `impl Baz`, which is not FFI-safe +error: `extern` block uses type `Qux`, which is not FFI-safe --> $DIR/lint-ctypes-73251-1.rs:23:25 | LL | pub fn lint_me() -> ::Assoc; diff --git a/src/test/ui/lint/lint-ctypes-73251-2.rs b/src/test/ui/lint/lint-ctypes-73251-2.rs index 717ca4986f700..df71a94579624 100644 --- a/src/test/ui/lint/lint-ctypes-73251-2.rs +++ b/src/test/ui/lint/lint-ctypes-73251-2.rs @@ -33,7 +33,7 @@ fn use_of_b() -> AliasB { } extern "C" { - pub fn lint_me() -> ::Assoc; //~ ERROR: uses type `impl TraitA` + pub fn lint_me() -> ::Assoc; //~ ERROR: uses type `AliasA` } fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73251-2.stderr b/src/test/ui/lint/lint-ctypes-73251-2.stderr index d7e10db441ec2..64f0fb2d892a4 100644 --- a/src/test/ui/lint/lint-ctypes-73251-2.stderr +++ b/src/test/ui/lint/lint-ctypes-73251-2.stderr @@ -1,4 +1,4 @@ -error: `extern` block uses type `impl TraitA`, which is not FFI-safe +error: `extern` block uses type `AliasA`, which is not FFI-safe --> $DIR/lint-ctypes-73251-2.rs:36:25 | LL | pub fn lint_me() -> ::Assoc; diff --git a/src/test/ui/lint/opaque-ty-ffi-unsafe.rs b/src/test/ui/lint/opaque-ty-ffi-unsafe.rs index 3a62b6a21a56a..b7cc38e99fc37 100644 --- a/src/test/ui/lint/opaque-ty-ffi-unsafe.rs +++ b/src/test/ui/lint/opaque-ty-ffi-unsafe.rs @@ -9,7 +9,7 @@ pub fn ret_closure() -> A { extern "C" { pub fn a(_: A); - //~^ ERROR `extern` block uses type `impl Fn()`, which is not FFI-safe [improper_ctypes] + //~^ ERROR `extern` block uses type `A`, which is not FFI-safe [improper_ctypes] } fn main() {} diff --git a/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr b/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr index 5afbef778b3e3..62d00fd6835ee 100644 --- a/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr +++ b/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr @@ -1,4 +1,4 @@ -error: `extern` block uses type `impl Fn()`, which is not FFI-safe +error: `extern` block uses type `A`, which is not FFI-safe --> $DIR/opaque-ty-ffi-unsafe.rs:11:17 | LL | pub fn a(_: A); diff --git a/src/test/ui/traits/alias/issue-83613.rs b/src/test/ui/traits/alias/issue-83613.rs index 0013d5d66f172..04320e7207683 100644 --- a/src/test/ui/traits/alias/issue-83613.rs +++ b/src/test/ui/traits/alias/issue-83613.rs @@ -8,6 +8,6 @@ fn mk_opaque() -> OpaqueType { trait AnotherTrait {} impl AnotherTrait for T {} impl AnotherTrait for OpaqueType {} -//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `impl OpaqueTrait` +//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `OpaqueType` //~| ERROR cannot implement trait on type alias impl trait fn main() {} diff --git a/src/test/ui/traits/alias/issue-83613.stderr b/src/test/ui/traits/alias/issue-83613.stderr index 6a3498a389375..4f19e6607c8d9 100644 --- a/src/test/ui/traits/alias/issue-83613.stderr +++ b/src/test/ui/traits/alias/issue-83613.stderr @@ -10,13 +10,13 @@ note: type alias impl trait defined here LL | type OpaqueType = impl OpaqueTrait; | ^^^^^^^^^^^^^^^^ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `impl OpaqueTrait` +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType` --> $DIR/issue-83613.rs:10:1 | LL | impl AnotherTrait for T {} | -------------------------------- first implementation here LL | impl AnotherTrait for OpaqueType {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `impl OpaqueTrait` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType` error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr b/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr index 4a49d6e4ab8fd..0664275b2ad0a 100644 --- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr +++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr @@ -2,15 +2,15 @@ error[E0277]: `Rc` cannot be sent between threads safely --> $DIR/auto-trait-leakage2.rs:17:13 | LL | type Foo = impl std::fmt::Debug; - | -------------------- within this `impl Debug` + | -------------------- within this `Foo` ... LL | is_send(m::foo()); | ------- ^^^^^^^^ `Rc` cannot be sent between threads safely | | | required by a bound introduced by this call | - = help: within `impl Debug`, the trait `Send` is not implemented for `Rc` - = note: required because it appears within the type `impl Debug` + = help: within `Foo`, the trait `Send` is not implemented for `Rc` + = note: required because it appears within the type `Foo` note: required by a bound in `is_send` --> $DIR/auto-trait-leakage2.rs:14:15 | diff --git a/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr index d61561d3ea937..26308c6ff6b15 100644 --- a/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr +++ b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr @@ -15,7 +15,7 @@ LL | pub type Boo = impl ::std::fmt::Debug; LL | "" | ^^ expected opaque type, found `&str` | - = note: expected opaque type `impl Debug` + = note: expected opaque type `Boo` found reference `&str` error: aborting due to 2 previous errors 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 950d9bbf245ca..4b7dbbd6a56cc 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63279.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-63279.stderr @@ -25,7 +25,7 @@ LL | type Closure = impl FnOnce(); LL | || -> Closure { || () } | ^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found closure | - = note: expected opaque type `impl FnOnce()` + = note: expected opaque type `Closure` found closure `[closure@$DIR/issue-63279.rs:8:5: 8:28]` error: aborting due to 3 previous errors 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 c11585db077e2..38591e37f5358 100644 --- a/src/test/ui/type-alias-impl-trait/issue-74280.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-74280.stderr @@ -7,7 +7,7 @@ LL | type Test = impl Copy; LL | 7 | ^ expected `()`, found integer | - = note: expected opaque type `impl Copy` + = note: expected opaque type `Test` found type `{integer}` error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/issue-77179.stderr b/src/test/ui/type-alias-impl-trait/issue-77179.stderr index 9e742a2550029..053546e4b9285 100644 --- a/src/test/ui/type-alias-impl-trait/issue-77179.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-77179.stderr @@ -5,7 +5,7 @@ LL | fn test() -> Pointer<_> { | --------^- | | | | | not allowed in type signatures - | help: replace with the correct return type: `impl Deref` + | help: replace with the correct return type: `Pointer` error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr index 20da37ec9a186..db4b60461ef38 100644 --- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr @@ -11,7 +11,7 @@ LL | fn g(a: A, b: B) -> (X, X` found type parameter `B` = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs index d51c4185fbc4a..784a6c75886d4 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs @@ -12,7 +12,7 @@ impl Foo<()> for () { } fn foo() -> impl Foo { // FIXME(type-alias-impl-trait): We could probably make this work. () - //~^ ERROR: the trait bound `(): Foo` is not satisfied + //~^ ERROR: the trait bound `(): Foo` is not satisfied } fn main() { } diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr index 630328afc52c4..9472cac63554e 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `(): Foo` is not satisfied +error[E0277]: the trait bound `(): Foo` is not satisfied --> $DIR/nested-tait-inference.rs:14:5 | LL | () - | ^^ the trait `Foo` is not implemented for `()` + | ^^ the trait `Foo` is not implemented for `()` | = help: the following implementations were found: <() as Foo<()>> diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs index 00d835d3ca774..00bd44c493c83 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs @@ -12,7 +12,7 @@ impl Foo for () {} fn foo() -> impl Foo { () - //~^ ERROR: the trait bound `(): Foo` is not satisfied + //~^ ERROR: the trait bound `(): Foo` is not satisfied } fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr index 1b04ea2bf167c..ec1b4642d0822 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `(): Foo` is not satisfied +error[E0277]: the trait bound `(): Foo` is not satisfied --> $DIR/nested-tait-inference2.rs:14:5 | LL | () - | ^^ the trait `Foo` is not implemented for `()` + | ^^ the trait `Foo` is not implemented for `()` | = help: the following implementations were found: <() as Foo<()>> diff --git a/src/test/ui/type-alias-impl-trait/nested.rs b/src/test/ui/type-alias-impl-trait/nested.rs index e55fe3a3aafe7..6b866be7d173f 100644 --- a/src/test/ui/type-alias-impl-trait/nested.rs +++ b/src/test/ui/type-alias-impl-trait/nested.rs @@ -13,5 +13,5 @@ fn bar() -> Bar { fn main() { println!("{:?}", bar()); - //~^ ERROR `impl Trait` doesn't implement `Debug` + //~^ ERROR `Bar` doesn't implement `Debug` } diff --git a/src/test/ui/type-alias-impl-trait/nested.stderr b/src/test/ui/type-alias-impl-trait/nested.stderr index eff56e3b76d9c..cf4d23656e0e1 100644 --- a/src/test/ui/type-alias-impl-trait/nested.stderr +++ b/src/test/ui/type-alias-impl-trait/nested.stderr @@ -1,10 +1,10 @@ -error[E0277]: `impl Trait` doesn't implement `Debug` +error[E0277]: `Bar` doesn't implement `Debug` --> $DIR/nested.rs:15:22 | LL | println!("{:?}", bar()); - | ^^^^^ `impl Trait` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^ `Bar` cannot be formatted using `{:?}` because it doesn't implement `Debug` | - = help: the trait `Debug` is not implemented for `impl Trait` + = help: the trait `Debug` is not implemented for `Bar` = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr b/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr index d12160a979312..e691d8781c0f1 100644 --- a/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr +++ b/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr @@ -8,7 +8,7 @@ LL | let _: &str = bomp(); | ^^^^^^ expected `&str`, found opaque type | = note: expected reference `&str` - found opaque type `impl Debug` + found opaque type `Boo` error[E0308]: mismatched types --> $DIR/no_revealing_outside_defining_module.rs:19:5 @@ -19,7 +19,7 @@ LL | pub type Boo = impl ::std::fmt::Debug; LL | "" | ^^ expected opaque type, found `&str` | - = note: expected opaque type `impl Debug` + = note: expected opaque type `Boo` found reference `&str` error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/self-referential-2.rs b/src/test/ui/type-alias-impl-trait/self-referential-2.rs index e9ace992c8b9d..dc7054da5ec19 100644 --- a/src/test/ui/type-alias-impl-trait/self-referential-2.rs +++ b/src/test/ui/type-alias-impl-trait/self-referential-2.rs @@ -4,7 +4,7 @@ type Foo = impl std::fmt::Debug; type Bar = impl PartialEq; fn bar() -> Bar { - 42_i32 //~ ERROR can't compare `i32` with `impl Debug` + 42_i32 //~ ERROR can't compare `i32` with `Foo` } fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/self-referential-2.stderr b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr index 2c3630dc39425..6997676260dd6 100644 --- a/src/test/ui/type-alias-impl-trait/self-referential-2.stderr +++ b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr @@ -1,10 +1,10 @@ -error[E0277]: can't compare `i32` with `impl Debug` +error[E0277]: can't compare `i32` with `Foo` --> $DIR/self-referential-2.rs:7:5 | LL | 42_i32 - | ^^^^^^ no implementation for `i32 == impl Debug` + | ^^^^^^ no implementation for `i32 == Foo` | - = help: the trait `PartialEq` is not implemented for `i32` + = help: the trait `PartialEq` is not implemented for `i32` error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/self-referential-4.rs b/src/test/ui/type-alias-impl-trait/self-referential-4.rs new file mode 100644 index 0000000000000..697ec56825a9c --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/self-referential-4.rs @@ -0,0 +1,25 @@ +#![feature(type_alias_impl_trait)] + +type Bar<'a, 'b> = impl PartialEq> + std::fmt::Debug; + +fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { + i //~ ERROR can't compare `&i32` with `Bar<'b, 'static>` +} + +type Foo<'a, 'b> = impl PartialEq> + std::fmt::Debug; + +fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> { + i //~ ERROR can't compare `&i32` with `Foo<'static, 'b>` +} + +type Moo<'a, 'b> = impl PartialEq> + std::fmt::Debug; + +fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> { + i //~ ERROR can't compare `&i32` with `Moo<'static, 'a>` +} + +fn main() { + let meh = 42; + let muh = 69; + assert_eq!(bar(&meh), bar(&meh)); +} diff --git a/src/test/ui/type-alias-impl-trait/self-referential-4.stderr b/src/test/ui/type-alias-impl-trait/self-referential-4.stderr new file mode 100644 index 0000000000000..4a6ee2f9279d1 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/self-referential-4.stderr @@ -0,0 +1,27 @@ +error[E0277]: can't compare `&i32` with `Bar<'b, 'static>` + --> $DIR/self-referential-4.rs:6:5 + | +LL | i + | ^ no implementation for `&i32 == Bar<'b, 'static>` + | + = help: the trait `PartialEq>` is not implemented for `&i32` + +error[E0277]: can't compare `&i32` with `Foo<'static, 'b>` + --> $DIR/self-referential-4.rs:12:5 + | +LL | i + | ^ no implementation for `&i32 == Foo<'static, 'b>` + | + = help: the trait `PartialEq>` is not implemented for `&i32` + +error[E0277]: can't compare `&i32` with `Moo<'static, 'a>` + --> $DIR/self-referential-4.rs:18:5 + | +LL | i + | ^ no implementation for `&i32 == Moo<'static, 'a>` + | + = help: the trait `PartialEq>` is not implemented for `&i32` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/self-referential.rs b/src/test/ui/type-alias-impl-trait/self-referential.rs index 46468bc98b968..4974ac72dad18 100644 --- a/src/test/ui/type-alias-impl-trait/self-referential.rs +++ b/src/test/ui/type-alias-impl-trait/self-referential.rs @@ -3,7 +3,19 @@ type Bar<'a, 'b> = impl PartialEq> + std::fmt::Debug; fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { - i //~ ERROR can't compare `&i32` with `impl PartialEq + i //~ ERROR can't compare `&i32` with `Bar<'b, 'a>` +} + +type Foo<'a, 'b> = (i32, impl PartialEq> + std::fmt::Debug); + +fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> { + (42, i) //~ ERROR can't compare `&i32` with `(i32, &i32)` +} + +type Moo<'a, 'b> = (i32, impl PartialEq> + std::fmt::Debug); + +fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> { + (42, i) //~ ERROR can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})` } fn main() { diff --git a/src/test/ui/type-alias-impl-trait/self-referential.stderr b/src/test/ui/type-alias-impl-trait/self-referential.stderr index 29f1e0bec083d..0626e6be0d5a5 100644 --- a/src/test/ui/type-alias-impl-trait/self-referential.stderr +++ b/src/test/ui/type-alias-impl-trait/self-referential.stderr @@ -1,11 +1,27 @@ -error[E0277]: can't compare `&i32` with `impl PartialEq::{opaque#0}> + Debug` +error[E0277]: can't compare `&i32` with `Bar<'b, 'a>` --> $DIR/self-referential.rs:6:5 | LL | i - | ^ no implementation for `&i32 == impl PartialEq::{opaque#0}> + Debug` + | ^ no implementation for `&i32 == Bar<'b, 'a>` | - = help: the trait `PartialEq::{opaque#0}> + Debug>` is not implemented for `&i32` + = help: the trait `PartialEq>` is not implemented for `&i32` -error: aborting due to previous error +error[E0277]: can't compare `&i32` with `(i32, &i32)` + --> $DIR/self-referential.rs:12:10 + | +LL | (42, i) + | ^ no implementation for `&i32 == (i32, &i32)` + | + = help: the trait `PartialEq<(i32, &i32)>` is not implemented for `&i32` + +error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})` + --> $DIR/self-referential.rs:18:10 + | +LL | (42, i) + | ^ no implementation for `&i32 == (i32, Moo<'b, 'a>::{opaque#0})` + | + = help: the trait `PartialEq<(i32, Moo<'b, 'a>::{opaque#0})>` is not implemented for `&i32` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs index e0d24146179bc..cab742d23f57d 100644 --- a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs +++ b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs @@ -13,7 +13,7 @@ const LEAK_FREE: Bar = leak_free(); fn leak_free_test() { match LEAK_FREE { LEAK_FREE => (), - //~^ `impl Send` cannot be used in patterns + //~^ `Bar` cannot be used in patterns _ => (), } } diff --git a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr index 7e41b374452a3..aacc0cc7aa69b 100644 --- a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr +++ b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr @@ -1,4 +1,4 @@ -error: `impl Send` cannot be used in patterns +error: `Bar` cannot be used in patterns --> $DIR/structural-match-no-leak.rs:15:9 | LL | LEAK_FREE => (), diff --git a/src/test/ui/type-alias-impl-trait/structural-match.rs b/src/test/ui/type-alias-impl-trait/structural-match.rs index 1a2c373bac124..c8825c68e33cc 100644 --- a/src/test/ui/type-alias-impl-trait/structural-match.rs +++ b/src/test/ui/type-alias-impl-trait/structural-match.rs @@ -14,7 +14,7 @@ const VALUE: Foo = value(); fn test() { match VALUE { VALUE => (), - //~^ `impl Send` cannot be used in patterns + //~^ `Foo` cannot be used in patterns _ => (), } } diff --git a/src/test/ui/type-alias-impl-trait/structural-match.stderr b/src/test/ui/type-alias-impl-trait/structural-match.stderr index b43f2148dea5e..28ae9c212d979 100644 --- a/src/test/ui/type-alias-impl-trait/structural-match.stderr +++ b/src/test/ui/type-alias-impl-trait/structural-match.stderr @@ -1,4 +1,4 @@ -error: `impl Send` cannot be used in patterns +error: `Foo` cannot be used in patterns --> $DIR/structural-match.rs:16:9 | LL | VALUE => (), diff --git a/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr b/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr index eccd3f9048f0e..1dabe4586c5b9 100644 --- a/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr +++ b/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr @@ -2,7 +2,7 @@ error[E0382]: use of moved value: `x` --> $DIR/type_of_a_let.rs:16:16 | LL | let x: Foo = 22_u32; - | - move occurs because `x` has type `impl Debug`, which does not implement the `Copy` trait + | - move occurs because `x` has type `Foo`, which does not implement the `Copy` trait LL | let y: Foo = x; | - value moved here LL | same_type((x, y)); @@ -12,7 +12,7 @@ error[E0382]: use of moved value: `y` --> $DIR/type_of_a_let.rs:17:5 | LL | let y: Foo = x; - | - move occurs because `y` has type `impl Debug`, which does not implement the `Copy` trait + | - move occurs because `y` has type `Foo`, which does not implement the `Copy` trait LL | same_type((x, y)); | - value moved here LL | y From 9822fff2ea892fed6da7d219c945c0b30de3c7a3 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 7 Feb 2022 16:04:23 +0000 Subject: [PATCH 53/53] Add a test showing that we don't infer across multiple uses of the same opaque type but with a different order of generic arguments --- .../multiple-def-uses-in-one-fn-infer.rs | 13 +++++++++++++ .../multiple-def-uses-in-one-fn-infer.stderr | 14 ++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs create mode 100644 src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs new file mode 100644 index 0000000000000..08cb48ccf308c --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs @@ -0,0 +1,13 @@ +// /~https://github.com/rust-lang/rust/issues/73481 +// This test used to cause unsoundness, since one of the two possible +// resolutions was chosen at random instead of erroring due to conflicts. + +#![feature(type_alias_impl_trait)] + +type Y = impl std::fmt::Debug; + +fn g() -> (Y, Y) { + (42_i64, 60) //~^ ERROR concrete type differs from previous defining opaque type use +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr new file mode 100644 index 0000000000000..3f57612684e41 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr @@ -0,0 +1,14 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/multiple-def-uses-in-one-fn-infer.rs:9:1 + | +LL | fn g() -> (Y, Y) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i64`, got `i32` + | +note: previous use here + --> $DIR/multiple-def-uses-in-one-fn-infer.rs:9:1 + | +LL | fn g() -> (Y, Y) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error +