diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 5597a8b091554..c318386f33b13 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..f24d881639920 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,44 @@ 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)| { + .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 - }) + 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); + 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 +116,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { span, ); - check_opaque_type_parameter_valid( - infcx.tcx, + ( opaque_type_key, - OpaqueTypeDecl { concrete_ty: remapped_type, ..decl }, + if check_opaque_type_parameter_valid(infcx.tcx, opaque_type_key, origin, span) { + remapped_type + } else { + infcx.tcx.ty_error() + }, ) - .then_some((opaque_type_key, remapped_type)) }) .collect() } @@ -149,9 +167,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 +196,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 73103643e3e16..4647610b0033d 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,7 +16,6 @@ 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::{ @@ -41,7 +41,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 +75,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)*), ), @@ -190,59 +190,44 @@ 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() - .filter_map(|(opaque_type_key, mut decl)| { - decl.concrete_ty = infcx.resolve_vars_if_possible(decl.concrete_ty); + .map(|(opaque_type_key, decl)| { + 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, - 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()), + decl.hidden_type.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() - { - *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, decl)) - } + (opaque_type_key, (hidden_type, decl.hidden_type.span, decl.origin)) }) .collect() }, @@ -274,7 +259,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 }; @@ -331,7 +316,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, @@ -467,7 +451,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); } @@ -526,10 +510,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> { @@ -554,7 +541,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() { @@ -599,7 +586,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. @@ -635,7 +622,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); @@ -697,7 +684,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 { @@ -906,7 +893,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 @@ -1056,17 +1043,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)); @@ -1207,131 +1196,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). - let opaque_type_map = self.infcx.inner.borrow().opaque_types.clone(); - for (opaque_type_key, opaque_decl) in opaque_type_map { - self.fully_perform_op( - locations, - ConstraintCategory::OpaqueType, - CustomTypeOp::new( - |infcx| { - infcx.constrain_opaque_type(opaque_type_key, &opaque_decl); - Ok(InferOk { value: (), obligations: vec![] }) - }, - || "opaque_type_map".to_string(), - ), - )?; - } - Ok(()) - } - fn tcx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -2773,20 +2637,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 cc3fe0a123c55..aba1dd2bc548c 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -1,13 +1,15 @@ 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; use rustc_middle::ty::{self, Const, Ty}; +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`: @@ -63,6 +65,10 @@ impl<'me, 'bccx, 'tcx> NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { } impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { + fn span(&self) -> Span { + self.locations.span(self.type_checker.body) + } + fn param_env(&self) -> ty::ParamEnv<'tcx> { self.type_checker.param_env } @@ -117,6 +123,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 { @@ -126,4 +135,33 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> fn forbid_inference_vars() -> bool { true } + + 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(); + 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| { + Ok(InferOk { + value: (), + obligations: vec![infcx.opaque_ty_obligation( + a, + b, + a_is_expected, + param_env, + cause, + )], + }) + }, + || "register_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..49a9b911f3a4b 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 within 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 within 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 cf15fc4ddc3a5..f8e5764878579 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -79,7 +79,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, @@ -171,9 +170,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 cc7ec9432faed..2f4b3844430e3 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 @@ -39,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 @@ -58,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 5b4a9d9dfad45..7d86f8a763c30 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; @@ -89,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, }) } @@ -133,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<(Ty<'tcx>, Ty<'tcx>)> { + self.inner + .borrow_mut() + .opaque_type_storage + .take_opaque_types() + .into_iter() + .map(|(k, v)| (self.tcx.mk_opaque(k.def_id, k.substs), v.hidden_type.ty)) + .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 @@ -223,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. @@ -344,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 @@ -372,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>, { @@ -474,7 +494,16 @@ 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 &(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 }) } /// Given a "guess" at the values for the canonical variables in @@ -631,6 +660,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 } @@ -686,4 +719,14 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> { fn forbid_inference_vars() -> bool { true } + + 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, + 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 90c0ff9226f77..9f6c6d3184533 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -66,18 +66,19 @@ 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); - match (a.kind(), b.kind()) { (&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => { infcx.inner.borrow_mut().type_variables().equate(a_id, b_id); @@ -91,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/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 d1b24b332bdcc..fa17a2d66f117 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}; @@ -192,18 +192,8 @@ pub struct InferCtxtInner<'tcx> { undo_log: InferCtxtUndoLogs<'tcx>, - // Opaque types found in explicit return types and their - // associated fresh inference variable. Writeback resolves these - // variables to get the concrete type, which can be used to - // 'de-opaque' OpaqueTypeDecl 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>>, + /// Caches for opaque type inference. + pub opaque_type_storage: OpaqueTypeStorage<'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] + pub 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, @@ -297,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, @@ -552,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> { @@ -560,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, + } } } @@ -584,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 @@ -608,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), @@ -734,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, @@ -741,6 +759,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { cause: None, param_env, obligations: PredicateObligations::new(), + define_opaque_types, } } @@ -1056,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 0a210ed053ce4..3a288516664e3 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -24,11 +24,13 @@ 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}; 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 +77,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 @@ -87,6 +90,8 @@ pub trait TypeRelatingDelegate<'tcx> { info: ty::VarianceDiagInfo<'tcx>, ); + 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>); /// Creates a new universe index. Used when instantiating placeholders. @@ -277,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() { @@ -286,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 @@ -531,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() { @@ -559,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.register_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 e7dca94806cb7..46420fbe0c305 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -1,10 +1,11 @@ -use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::{InferCtxt, InferOk}; -use crate::traits; +use crate::traits::{self, PredicateObligation}; +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::fold::BottomUpFolder; use rustc_middle::ty::subst::{GenericArgKind, Subst}; use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitor}; @@ -14,14 +15,28 @@ use std::ops::ControlFlow; pub type OpaqueTypeMap<'tcx> = VecMap, OpaqueTypeDecl<'tcx>>; +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). -#[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_type: OpaqueHiddenType<'tcx>, + + /// The origin of the opaque type. + pub origin: hir::OpaqueTyOrigin, +} +#[derive(Copy, Clone, Debug, TypeFoldable)] +pub struct OpaqueHiddenType<'tcx> { /// The span of this particular definition of the opaque type. So /// for example: /// @@ -35,7 +50,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, @@ -49,54 +64,132 @@ 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 - /// and creates appropriate obligations. For example, given the input: - /// - /// impl Iterator - /// - /// this method would create two type variables, `?0` and `?1`. It would - /// return the type `?0` but also the obligations: - /// - /// ?0: 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>( + pub fn handle_opaque_type( &self, - body_id: hir::HirId, + a: Ty<'tcx>, + b: 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 } + ) -> InferResult<'tcx, ()> { + if a.references_error() || b.references_error() { + return Ok(InferOk { value: (), obligations: vec![] }); + } + if self.defining_use_anchor.is_some() { + let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() { + ty::Opaque(def_id, substs) => { + if let ty::Opaque(did2, _) = *b.kind() { + // 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( + 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) { + res + } else if let Some(res) = process(b, a) { + 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); + let prev = self.inner.borrow_mut().opaque_types().register( + key, + OpaqueHiddenType { ty: hidden_ty, span: cause.span }, + origin, + ); + match prev { + Some(prev) => self.at(cause, param_env).eq(prev, hidden_ty), + None => Ok(InferOk { value: (), obligations: vec![] }), + } + } } /// Given the map `opaque_types` containing the opaque @@ -231,51 +324,23 @@ 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 constrain_opaque_type( + pub fn register_member_constraints( &self, + param_env: ty::ParamEnv<'tcx>, opaque_type_key: OpaqueTypeKey<'tcx>, - opaque_defn: &OpaqueTypeDecl<'tcx>, + concrete_ty: Ty<'tcx>, + span: Span, ) { 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 // @@ -319,7 +384,7 @@ 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, @@ -328,15 +393,34 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }); } - 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 ) }; @@ -347,11 +431,29 @@ 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() + } } // Visitor that requires that (almost) all regions in the type visited outlive @@ -426,180 +528,93 @@ where } } -struct Instantiator<'a, 'tcx> { - infcx: &'a InferCtxt<'a, 'tcx>, - body_id: hir::HirId, - param_env: ty::ParamEnv<'tcx>, - value_span: Span, - obligations: Vec>, +pub enum UseKind { + DefiningUse, + OpaqueUse, } -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); - } - - debug!( - "instantiate_opaque_types_in_map: \ - encountered opaque outside its definition scope \ - def_id={:?}", - def_id, - ); - } - } - - ty - }, - lt_op: |lt| lt, - ct_op: |ct| ct, - }) +impl UseKind { + pub fn is_defining(self) -> bool { + match self { + UseKind::DefiningUse => true, + UseKind::OpaqueUse => false, + } } +} +impl<'a, 'tcx> InferCtxt<'a, 'tcx> { #[instrument(skip(self), level = "debug")] - fn fold_opaque_ty( - &mut self, - ty: Ty<'tcx>, + fn register_hidden_type( + &self, opaque_type_key: OpaqueTypeKey<'tcx>, + cause: ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + hidden_ty: Ty<'tcx>, origin: hir::OpaqueTyOrigin, - ) -> Ty<'tcx> { - let infcx = self.infcx; - let tcx = infcx.tcx; + ) -> InferResult<'tcx, ()> { + let tcx = self.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_types.get(&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, - }); - // 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 = cause.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); + let mut obligations = vec![]; + let prev = self.inner.borrow_mut().opaque_types().register( + OpaqueTypeKey { def_id, substs }, + OpaqueHiddenType { ty: hidden_ty, span }, + origin, + ); + if let Some(prev) = prev { + 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); - 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() { - // 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() { + // 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, - traits::ObligationCause::misc(self.value_span, self.body_id), + self.infer_projection( + param_env, + projection_ty, + 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. + ty::Opaque(def_id2, substs2) if def_id == def_id2 && substs == substs2 => { + hidden_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() { - return tcx.ty_error(); + // No point on adding these obligations since there's a type error involved. + return Ok(InferOk { value: (), obligations: vec![] }); } + 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)); + obligations.push(traits::Obligation::new(cause.clone(), 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 new file mode 100644 index 0000000000000..9b8f225ce367b --- /dev/null +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -0,0 +1,88 @@ +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, UndoLog}; + +use super::{OpaqueHiddenType, OpaqueTypeDecl, OpaqueTypeMap}; + +#[derive(Default, Debug)] +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>, +} + +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_type = idx; + } else { + match self.opaque_types.remove(&key) { + None => bug!("reverted opaque type inference that was never registered: {:?}", key), + Some(_) => {} + } + } + } + + pub fn get_decl(&self, key: &OpaqueTypeKey<'tcx>) -> Option<&OpaqueTypeDecl<'tcx>> { + self.opaque_types.get(key) + } + + pub fn opaque_types(&self) -> OpaqueTypeMap<'tcx> { + self.opaque_types.clone() + } + + #[instrument(level = "debug")] + 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 } + } +} + +impl<'tcx> Drop for OpaqueTypeStorage<'tcx> { + fn drop(&mut self) { + if !self.opaque_types.is_empty() { + ty::tls::with(|tcx| { + tcx.sess.delay_span_bug(DUMMY_SP, &format!("{:?}", self.opaque_types)) + }); + } + } +} + +pub struct OpaqueTypeTable<'a, 'tcx> { + storage: &'a mut OpaqueTypeStorage<'tcx>, + + undo_log: &'a mut InferCtxtUndoLogs<'tcx>, +} + +impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> { + #[instrument(skip(self), level = "debug")] + pub fn register( + &mut self, + key: OpaqueTypeKey<'tcx>, + hidden_type: OpaqueHiddenType<'tcx>, + origin: OpaqueTyOrigin, + ) -> Option> { + if let Some(decl) = self.storage.opaque_types.get_mut(&key) { + 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 { hidden_type, origin }; + self.storage.opaque_types.insert(key, decl); + self.undo_log.push(UndoLog::OpaqueTypes(key, None)); + None + } +} 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 89db8f464b4e7..02b15baf8fb2d 100644 --- a/compiler/rustc_infer/src/infer/undo_log.rs +++ b/compiler/rustc_infer/src/infer/undo_log.rs @@ -4,13 +4,15 @@ 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}, traits, }; +use super::opaque_types::OpaqueHiddenType; + pub struct Snapshot<'tcx> { pub(crate) undo_len: usize, _marker: PhantomData<&'tcx ()>, @@ -18,6 +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>, Option>), TypeVariables(type_variable::UndoLog<'tcx>), ConstUnificationTable(sv::UndoLog>>), IntUnificationTable(sv::UndoLog>), @@ -64,6 +67,7 @@ impl_from! { impl<'tcx> Rollback> for InferCtxtInner<'tcx> { fn reverse(&mut self, undo: UndoLog<'tcx>) { match undo { + 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..44e3da11826cd 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..2fc901bdbff34 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -178,6 +178,12 @@ pub struct QueryResponse<'tcx, R> { pub var_values: CanonicalVarValues<'tcx>, pub region_constraints: QueryRegionConstraints<'tcx>, pub certainty: Certainty, + /// 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, } 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/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_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 8eb2793cc34e3..8bf760179e680 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -627,6 +627,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 @@ -986,6 +991,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::TypeOutlives(..) | PredicateKind::ConstEvaluatable(..) | PredicateKind::ConstEquate(..) + | PredicateKind::OpaqueType(..) | PredicateKind::TypeWellFormedFromEnv(..) => None, } } @@ -1004,6 +1010,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::ClosureKind(..) | PredicateKind::ConstEvaluatable(..) | PredicateKind::ConstEquate(..) + | PredicateKind::OpaqueType(..) | PredicateKind::TypeWellFormedFromEnv(..) => None, } } @@ -1044,7 +1051,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..6521957ec944c 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -644,20 +644,23 @@ 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()))); + 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); } - - 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) => { @@ -2607,6 +2610,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 7d4af6cfa4052..6b187f7da4c6d 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 @@ -1815,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 c95dff13d6615..36f2a80773ea3 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..cd12430a2a249 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 /// @@ -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( @@ -359,6 +354,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/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) }) 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/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 6634f3e364d32..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, @@ -1680,6 +1681,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/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index e7897887df706..274f8a3ef79fa 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.obligations)), + 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..a183a20a2fed0 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(res) => { + self.evaluate_predicates_recursively(previous_stack, res.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,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result>, ()> { self.infcx .at(&obligation.cause, obligation.param_env) + // 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) .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..741438b3d29cc 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -61,6 +61,14 @@ bitflags! { | TypeFlags::HAS_CT_INFER.bits | TypeFlags::HAS_TY_PLACEHOLDER.bits | TypeFlags::HAS_CT_PLACEHOLDER.bits + // 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 + | 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..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::{ @@ -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,20 +503,15 @@ 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))) - 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 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 18a0a8767d45b..d10d3e43b5b18 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,8 @@ 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() { - 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 +236,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 +614,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,24 +630,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), - ); - - let opaque_type_map = infcx.inner.borrow().opaque_types.clone(); - for (OpaqueTypeKey { def_id, substs }, opaque_defn) in opaque_type_map { - 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 @@ -672,7 +647,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 @@ -681,6 +656,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/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 0347b6a4ab82f..74341fef38e27 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -956,8 +956,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); diff --git a/compiler/rustc_typeck/src/check/fallback.rs b/compiler/rustc_typeck/src/check/fallback.rs index e5da33d113e7c..8513231782407 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_types_vars.get(ty).copied(); - 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. diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 0f9803b969fb7..e60893a658b3d 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -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/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), diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs index beb6b371b2bb8..b775f24f8efd8 100644 --- a/compiler/rustc_typeck/src/check/inherited.rs +++ b/compiler/rustc_typeck/src/check/inherited.rs @@ -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..d4be3889a7ae7 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -341,6 +341,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, 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) 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 ec88bdf4a370f..e04c1423cdac8 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,64 +495,18 @@ 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) { - let opaque_types = self.fcx.infcx.inner.borrow().opaque_types.clone(); - for (opaque_type_key, opaque_defn) in opaque_types { - let hir_id = - self.tcx().hir().local_def_id_to_hir_id(opaque_type_key.def_id.expect_local()); - let instantiated_ty = self.resolve(opaque_defn.concrete_ty, &hir_id); - - 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; - } + #[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, 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)) } - } - - 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); - } + 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 5cb0d309ff4ee..912a16ffb8a13 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -389,28 +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(|| { - 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 - { + 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. 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()), - ) + 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); @@ -604,7 +598,21 @@ 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) { + // ```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. + // ``` + 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; } @@ -658,7 +666,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 +674,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 +682,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 +692,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 @@ -716,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/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/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 = diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index cfdd119377f17..66cbf884a027b 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..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 @@ -30,7 +30,7 @@ impl Thing for AssocNoCopy { type Out = Box>; 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..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 @@ -1,8 +1,10 @@ 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:33: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::Out::{opaque#0}>` error: aborting due to previous error 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/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..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,8 +1,8 @@ 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 { + | ^^^^^^^^^^ 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..cb50c70f99847 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..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,8 +1,8 @@ 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 { + | ^^^^^^^^^^ 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..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,12 +14,16 @@ 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> { - | -- ^^^^^^^^^^^^^^ - | | - | hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here +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 | | } + | |_^ | help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound | 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..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 @@ -1,19 +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 + --> $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> { - | -- ^^^^^^^^^^^^^^ - | | - | hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here +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 | | } + | |_^ | help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound | 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..eaa90a8e60a23 100644 --- a/src/test/ui/generator/issue-88653.stderr +++ b/src/test/ui/generator/issue-88653.stderr @@ -1,11 +1,11 @@ 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) -> _` + | ^^^^^ + | | + | expected signature of `fn((bool,)) -> _` + | found 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..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,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 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 93513a4563f07..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,11 +1,10 @@ -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/issue-87258_a.rs:19:21 +error: unconstrained opaque type + --> $DIR/issue-87258_a.rs:18:26 | -LL | fn foo<'a>() -> Self::FooFuture<'a> { - | ^^^^^^^^^^^^^^^^^^^ +LL | type FooFuture<'a> = impl Trait1; + | ^^^^^^^^^^^ | - = note: hidden type `Struct<'_>` captures lifetime '_#7r + = note: `FooFuture` must be used in combination with a concrete type within the same module 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..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,10 +15,11 @@ pub trait Trait2 { } type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1; +//~^ ERROR unconstrained opaque type 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..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,11 +1,10 @@ -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/issue-87258_b.rs:21:21 +error: unconstrained opaque type + --> $DIR/issue-87258_b.rs:17:49 | -LL | fn foo<'a>() -> Self::FooFuture<'a> { - | ^^^^^^^^^^^^^^^^^^^ +LL | type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1; + | ^^^^^^^^^^^ | - = note: hidden type `Struct<'_>` captures lifetime '_#7r + = note: `Helper` must be used in combination with a concrete type within the same module 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.rs b/src/test/ui/generic-associated-types/issue-88595.rs index e397390783f66..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: could not find defining uses 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 cb462871ccd32..e1d55fa228c2e 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:22:35 | LL | fn a(&'a self) -> Self::B<'a> {} - | ^^^^^^^^^^^ + | ^^ | note: lifetime used multiple times --> $DIR/issue-88595.rs:18:6 @@ -29,12 +29,6 @@ LL | impl<'a> A<'a> for C { LL | type B<'b> = impl Clone; | ^^ -error: could not find defining uses - --> $DIR/issue-88595.rs:19:18 - | -LL | type B<'b> = impl Clone; - | ^^^^^^^^^^ - -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/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/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/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..4032fbbceba4c 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -12,19 +12,13 @@ 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 -LL | } + | -------- the expected opaque type +... 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 + = note: expected opaque type `impl Foo` + found type `u32` error[E0277]: cannot add `impl Foo` to `u32` --> $DIR/equality.rs:24:11 @@ -35,10 +29,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..a75b9b43b3e8b 100644 --- a/src/test/ui/impl-trait/issue-55872-1.rs +++ b/src/test/ui/impl-trait/issue-55872-1.rs @@ -10,11 +10,10 @@ 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 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..efc57da746132 100644 --- a/src/test/ui/impl-trait/issue-55872-1.stderr +++ b/src/test/ui/impl-trait/issue-55872-1.stderr @@ -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:14: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:14: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,20 +31,7 @@ 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: 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-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..f50b31ff496ae --- /dev/null +++ b/src/test/ui/impl-trait/issue-55872-3.rs @@ -0,0 +1,20 @@ +// 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; + 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..bafd31f0083e8 --- /dev/null +++ b/src/test/ui/impl-trait/issue-55872-3.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `impl Future: Copy` is not satisfied + --> $DIR/issue-55872-3.rs:15:9 + | +LL | async {} + | ^^^^^^^^ the trait `Copy` is not implemented for `impl Future` + +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.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..cf2c8b7e41540 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)) } diff --git a/src/test/ui/impl-trait/issue-72911.stderr b/src/test/ui/impl-trait/issue-72911.stderr index e57fbf104dc6f..4a990286d966d 100644 --- a/src/test/ui/impl-trait/issue-72911.stderr +++ b/src/test/ui/impl-trait/issue-72911.stderr @@ -10,25 +10,15 @@ 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]>` -... -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 -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..8169cfafac711 100644 --- a/src/test/ui/impl-trait/issues/issue-70877.rs +++ b/src/test/ui/impl-trait/issues/issue-70877.rs @@ -4,7 +4,7 @@ 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); @@ -28,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 index fe48e92da5eac..8813bff3c353e 100644 --- a/src/test/ui/impl-trait/issues/issue-70877.stderr +++ b/src/test/ui/impl-trait/issues/issue-70877.stderr @@ -1,20 +1,19 @@ -error[E0271]: type mismatch resolving `::Item == Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` - --> $DIR/issue-70877.rs:7:12 +error: opaque type's hidden type cannot be another opaque type from the same scope + --> $DIR/issue-70877.rs:31: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)>` +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 | -note: expected this to be `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` - --> $DIR/issue-70877.rs:13:17 +LL | fn oof() -> impl std::fmt::Debug { + | ^^^^^^^^^^^^^^^^^^^^ +note: opaque type being used as hidden type + --> $DIR/issue-70877.rs:4:15 | -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)>` +LL | type FooRet = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ 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/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/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 new file mode 100644 index 0000000000000..2ea35270a7e3b --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-88236.rs @@ -0,0 +1,19 @@ +// check-pass + +// 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 main() {} 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..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 @@ -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,7 @@ where // 'a in ['d, 'e] // ``` if condition() { a } else { b } + //~^ 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..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,10 +1,11 @@ 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: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 + | -- 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.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs index d4c60a4e89209..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 @@ -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,7 @@ 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 } 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..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,10 +1,11 @@ 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: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 + | -- 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/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/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/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/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..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 @@ -2,46 +2,25 @@ 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 -LL | } + | ------------------ the expected opaque type +... 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 + = 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 | fn cat() -> impl ObjectSafe { - | --------------- expected because this return type... -LL | if true { -LL | return A; - | - ...is found to be `A` here -LL | } + | --------------- the expected opaque type +... 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) - | + = 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.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..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 @@ -2,82 +2,40 @@ 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 -LL | } + | ---------------------- the expected opaque type +... 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) - | + = 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 | fn bar() -> impl std::fmt::Display { - | ---------------------- expected because this return type... -LL | if false { -LL | return 0i32; - | ---- ...is found to be `i32` here -LL | } else { + | ---------------------- the expected opaque type +... 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); - | + = 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: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 + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:17:5 | -LL ~ return Box::new(0i32); -LL | } else { -LL ~ Box::new(1u32) +LL | fn baz() -> impl std::fmt::Display { + | ---------------------- the expected opaque type +LL | / if false { +LL | | return 0i32; +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 @@ -103,87 +61,50 @@ 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 + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:33:5 | -LL ~ 0 => return Box::new(0i32), -LL ~ _ => Box::new(1u32), +LL | fn bat() -> impl std::fmt::Display { + | ---------------------- the expected opaque type +LL | / match 13 { +LL | | 0 => return 0i32, +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 { - | ---------------------- expected because this return type... + | ---------------------- the expected opaque type LL | / match 13 { LL | | 0 => return 0i32, - | | ---- ...is found to be `i32` here 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 ~ }) - | + = 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:53:13 + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:48:5 | -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) +LL | fn cat() -> impl std::fmt::Display { + | ---------------------- the expected opaque type +LL | / match 13 { +LL | | 0 => { +LL | | return 0i32; +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 @@ -196,16 +117,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 +129,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/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..a60e34c17b671 --- /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 unconstrained opaque type + + 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 unconstrained opaque type + + 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..eae7d38d1162b --- /dev/null +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr @@ -0,0 +1,18 @@ +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: 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/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() {} 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/two_tait_defining_each_other.rs b/src/test/ui/impl-trait/two_tait_defining_each_other.rs new file mode 100644 index 0000000000000..6eb2a11b22c5f --- /dev/null +++ b/src/test/ui/impl-trait/two_tait_defining_each_other.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] + +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 + //~^ ERROR opaque type's hidden type cannot be another opaque type +} + +struct Bar; +impl Foo for Bar {} + +fn main() {} 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 new file mode 100644 index 0000000000000..3b16d0f5e047f --- /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; +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; +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..ef2089a6c5b17 --- /dev/null +++ b/src/test/ui/impl-trait/two_tait_defining_each_other2.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_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; + | ^^^^^^^^ + +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..37f8ae1b84b55 --- /dev/null +++ b/src/test/ui/impl-trait/two_tait_defining_each_other3.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] + +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) + //~^ 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 +} + +struct Bar; +impl Foo for Bar {} + +fn main() {} 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/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/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/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/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..26ce9b93105e6 --- /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 unconstrained opaque type + +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..121019d5f69ae --- /dev/null +++ b/src/test/ui/never_type/impl_trait_fallback3.stderr @@ -0,0 +1,10 @@ +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/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..42ff1866893e6 100644 --- a/src/test/ui/nll/issue-52113.stderr +++ b/src/test/ui/nll/issue-52113.stderr @@ -1,13 +1,13 @@ 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 | | | 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/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..42d9f057aaa08 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr +++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -1,10 +1,10 @@ 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> { - | -- ^^^^^^^^^^^^ - | | - | 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 | 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/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/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..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,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-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 | 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/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/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-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/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..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,13 +7,12 @@ trait TraitWithAssoc { } type Foo = impl Trait; -//~^ ERROR could not find defining uses trait Trait {} impl Trait for () {} fn foo_desugared(_: T) -> Foo { - //~^ ERROR non-defining opaque type use in defining scope () + //~^ 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 03e696fe89803..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,8 +1,8 @@ error: non-defining opaque type use in defining scope - --> $DIR/bound_reduction2.rs:16:46 + --> $DIR/bound_reduction2.rs:16:5 | -LL | fn foo_desugared(_: T) -> Foo { - | ^^^^^^^^^^^^^ +LL | () + | ^^ | note: used non-generic type `::Assoc` for generic parameter --> $DIR/bound_reduction2.rs:9:10 @@ -10,11 +10,5 @@ note: used non-generic type `::Assoc` for generic parameter LL | type Foo = impl Trait; | ^ -error: could not find defining uses - --> $DIR/bound_reduction2.rs:9:15 - | -LL | type Foo = impl Trait; - | ^^^^^^^^^^^^^ - -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 eecef2338c146..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,11 +4,11 @@ #![feature(type_alias_impl_trait)] type X<'a> = impl Into<&'static str> + From<&'a str>; -//~^ ERROR mismatched types 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..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,26 +1,19 @@ 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> { | ^^^^^^^^^^^ | = 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:10: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 - | -LL | type X<'a> = impl Into<&'static str> + From<&'a str>; - | ^^ - = note: ...does not necessarily outlive the static lifetime + | -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type +... +LL | t + | ^ error: aborting due to previous error; 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_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 0b4c262bbb43b..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 @@ -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 @@ -10,13 +12,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` + = 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/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/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)] 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..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,9 +3,9 @@ fn main() {} 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..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 @@ -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 @@ -10,11 +10,5 @@ note: lifetime used multiple times LL | type Two<'a, 'b> = impl std::fmt::Debug; | ^^ ^^ -error: could not find defining uses - --> $DIR/generic_duplicate_lifetime_param.rs:5:20 - | -LL | type Two<'a, 'b> = impl std::fmt::Debug; - | ^^^^^^^^^^^^^^^^^^^^ - -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 33cd2f6ba0753..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,23 +6,23 @@ fn main() {} // test that unused generic parameters are ok type TwoTys = impl Debug; -//~^ ERROR could not find defining uses + type TwoLifetimes<'a, 'b> = impl Debug; -//~^ ERROR could not find defining uses + 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..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 @@ -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 @@ -10,17 +10,11 @@ note: type used multiple times LL | type TwoTys = impl Debug; | ^ ^ -error: could not find defining uses - --> $DIR/generic_duplicate_param_use.rs:8:21 - | -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 @@ -28,17 +22,11 @@ note: lifetime used multiple times LL | type TwoLifetimes<'a, 'b> = impl Debug; | ^^ ^^ -error: could not find defining uses - --> $DIR/generic_duplicate_param_use.rs:10:29 - | -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 @@ -46,11 +34,5 @@ note: constant used multiple times LL | type TwoConsts = impl Debug; | ^ ^ -error: could not find defining uses - --> $DIR/generic_duplicate_param_use.rs:12:50 - | -LL | type TwoConsts = impl Debug; - | ^^^^^^^^^^ - -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 04fb57b39c052..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 { - //~^ ERROR non-defining opaque type use in defining scope - t -} - 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 fca9b70d18441..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:11:27 - | -LL | fn one(t: T) -> Two { - | ^^^^^^^^^ - | -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 1a755d3902612..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 { - //~^ ERROR non-defining opaque type use in defining scope - t -} - 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 90b04c043a00c..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:11:27 - | -LL | fn one(t: T) -> Two { - | ^^^^^^^^^ - | -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 50d95c83d58e6..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 { - //~^ ERROR non-defining opaque type use in defining scope - t -} - 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 c4be2fa83f130..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:11:27 - | -LL | fn one(t: T) -> Two { - | ^^^^^^^^^ - | -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 cf43085877f4c..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,25 +5,25 @@ use std::fmt::Debug; fn main() {} type OneTy = impl Debug; -//~^ ERROR could not find defining uses + type OneLifetime<'a> = impl Debug; -//~^ ERROR could not find defining uses + type OneConst = impl Debug; -//~^ ERROR could not find defining uses + // 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..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 @@ -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 @@ -10,32 +10,20 @@ note: used non-generic type `u32` for generic parameter LL | type OneTy = impl Debug; | ^ -error: could not find defining uses - --> $DIR/generic_nondefining_use.rs:7:17 - | -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> { - | ^^^^^^^^^^^^^^^^^^^^ - -error: could not find defining uses - --> $DIR/generic_nondefining_use.rs:9:24 - | -LL | type OneLifetime<'a> = impl Debug; - | ^^^^^^^^^^ +LL | 6u32 + | ^^^^ 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 @@ -43,11 +31,5 @@ note: used non-generic constant `123_usize` for generic parameter LL | type OneConst = impl Debug; | ^ -error: could not find defining uses - --> $DIR/generic_nondefining_use.rs:11:33 - | -LL | type OneConst = impl Debug; - | ^^^^^^^^^^ - -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_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..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 @@ -1,41 +1,29 @@ 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: expected type `i32` - found opaque type `impl Sized` - -error[E0310]: the parameter type `T` may not live long enough - --> $DIR/generic_type_does_not_live_long_enough.rs:12:30 + | ^ | -LL | fn wrong_generic(t: T) -> WrongGeneric { - | ^^^^^^^^^^^^^^^ +note: used non-generic type `&'static i32` for generic parameter + --> $DIR/generic_type_does_not_live_long_enough.rs:10:19 | - = help: consider adding an explicit lifetime bound `T: 'static`... +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:9:24 + --> $DIR/generic_type_does_not_live_long_enough.rs:14:5 | -LL | type WrongGeneric = impl 'static; - | ^^^^^^^^^^^^ +LL | t + | ^ | = 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 -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..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 @@ -3,13 +3,14 @@ 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 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..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 @@ -1,32 +1,29 @@ 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:14: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: aborting due to 3 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..608572978a351 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 @@ -17,7 +18,6 @@ mod m { fn baz() { 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..3ed86fae8a18d 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,24 @@ 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: aborting due to 2 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.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr index a4ccae4eb7ed9..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 @@ -1,38 +1,14 @@ 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 | ^^^^^ -error[E0308]: mismatched types - --> $DIR/issue-57611-trait-alias.rs:17:16 - | -LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other - | - = note: expected type `for<'r> Fn<(&'r X,)>` - found type `Fn<(&'static X,)>` -note: this closure does not fulfill the lifetime requirements - --> $DIR/issue-57611-trait-alias.rs:21:9 - | -LL | |x| x - | ^^^^^ - -error: implementation of `FnOnce` is not general enough - --> $DIR/issue-57611-trait-alias.rs:17:16 - | -LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough - | - = note: closure with signature `fn(&'static X) -> &'static X` must implement `FnOnce<(&'0 X,)>`, for any lifetime `'0`... - = note: ...but it actually implements `FnOnce<(&'static X,)>` - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs index 625e46b6bc012..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 @@ -17,8 +17,8 @@ impl Foo for X { type Bar = impl Baz; 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..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,8 +1,8 @@ error: implementation of `FnOnce` is not general enough - --> $DIR/issue-57611-trait-alias.rs:19:22 + --> $DIR/issue-57611-trait-alias.rs:20: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` 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..37a2f28ce074f 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60371.rs +++ b/src/test/ui/type-alias-impl-trait/issue-60371.rs @@ -11,7 +11,6 @@ impl Bug for &() { 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..3666b6e97ecfd 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60371.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60371.stderr @@ -11,21 +11,12 @@ error[E0277]: the trait bound `(): Bug` is not satisfied --> $DIR/issue-60371.rs:12: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 - | -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 = || (); - | ^^^^^ - -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-60564.rs b/src/test/ui/type-alias-impl-trait/issue-60564.rs index 44dcec2c3da98..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 could not find defining uses impl IterBits for T where @@ -18,8 +17,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..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,8 +1,8 @@ error: non-defining opaque type use in defining scope - --> $DIR/issue-60564.rs:20:34 + --> $DIR/issue-60564.rs:20: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 @@ -10,11 +10,5 @@ note: used non-generic type `u8` for generic parameter LL | type IterBitsIter = impl std::iter::Iterator; | ^ -error: could not find defining uses - --> $DIR/issue-60564.rs:8:30 - | -LL | type IterBitsIter = impl std::iter::Iterator; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error 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..057a908bbee74 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63279.rs +++ b/src/test/ui/type-alias-impl-trait/issue-63279.rs @@ -5,7 +5,10 @@ type Closure = impl FnOnce(); fn c() -> Closure { - || -> Closure { || () } //~ ERROR: mismatched types + || -> Closure { || () } + //~^ ERROR: mismatched types + //~| 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..4b7dbbd6a56cc 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,34 @@ +error[E0277]: expected a `FnOnce<()>` closure, found `()` + --> $DIR/issue-63279.rs:8: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:21 + | +LL | || -> Closure { || () } + | ^^^^^ expected `()`, found closure + | + = note: expected unit type `()` + found closure `[closure@$DIR/issue-63279.rs:8:21: 8:26]` + error[E0308]: mismatched types --> $DIR/issue-63279.rs:8:5 | LL | type Closure = impl FnOnce(); - | ------------- the found opaque type + | ------------- the expected 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 opaque type `Closure` + found closure `[closure@$DIR/issue-63279.rs:8:5: 8:28]` -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.rs b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs index 2e6354088ac5a..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 could not find defining uses + 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 721f99a3f0d18..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 @@ -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 @@ -10,11 +10,5 @@ note: used non-generic type `()` for generic parameter LL | type Alias<'a, U> = impl Trait; | ^ -error: could not find defining uses - --> $DIR/issue-68368-non-defining-use-2.rs:7:21 - | -LL | type Alias<'a, U> = impl Trait; - | ^^^^^^^^^^^^^ - -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 3addd8dcc4fb3..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 could not find defining uses + 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 f5b8fccf65d16..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 @@ -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 @@ -10,11 +10,5 @@ note: used non-generic type `()` for generic parameter LL | type Alias<'a, U> = impl Trait; | ^ -error: could not find defining uses - --> $DIR/issue-68368-non-defining-use.rs:7:21 - | -LL | type Alias<'a, U> = impl Trait; - | ^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error 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..38591e37f5358 100644 --- a/src/test/ui/type-alias-impl-trait/issue-74280.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-74280.stderr @@ -1,8 +1,14 @@ error[E0308]: mismatched types --> $DIR/issue-74280.rs:9:5 | +LL | type Test = impl Copy; + | --------- the expected opaque type +... LL | 7 | ^ expected `()`, found integer + | + = 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 15205ba9b419e..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: `Box` + | help: replace with the correct return type: `Pointer` 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/issue-93411.rs b/src/test/ui/type-alias-impl-trait/issue-93411.rs new file mode 100644 index 0000000000000..1f8c789267d1b --- /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 {} +} 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 + 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..f39bf4aeb29ae --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs @@ -0,0 +1,9 @@ +#![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() {} 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..49d08dda9f994 --- /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: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:5: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)); } 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..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 @@ -7,8 +7,8 @@ type X = impl Into<&'static A>; 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..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,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:10: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 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..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 @@ -1,6 +1,9 @@ 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 | | @@ -8,8 +11,8 @@ 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 efb88dabf34cd..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 @@ -1,5 +1,3 @@ -// check-pass - #![feature(type_alias_impl_trait)] #![allow(dead_code)] @@ -12,7 +10,9 @@ 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..9472cac63554e --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/nested-tait-inference.rs:14:5 + | +LL | () + | ^^ the trait `Foo` is not implemented for `()` + | + = help: the following implementations were found: + <() as Foo<()>> + +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 9b26a65297852..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 @@ -4,7 +4,6 @@ use std::fmt::Debug; type FooX = impl Debug; -//~^ ERROR: could not find defining uses trait Foo {} @@ -12,8 +11,8 @@ impl Foo<()> for () {} impl Foo for () {} fn foo() -> impl Foo { - //~^ ERROR: the trait bound `(): Foo` is not satisfied [E0277] () + //~^ 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 7e24ee644b1ce..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,19 +1,13 @@ -error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/nested-tait-inference2.rs:14:13 +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/nested-tait-inference2.rs:14:5 | -LL | fn foo() -> impl Foo { - | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` +LL | () + | ^^ the trait `Foo` is not implemented for `()` | = help: the following implementations were found: <() 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`. 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..fbab5470b4f6d --- /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; +//~^ unconstrained opaque type + +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..b1d947a9ccf4e --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr @@ -0,0 +1,10 @@ +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/nested.rs b/src/test/ui/type-alias-impl-trait/nested.rs new file mode 100644 index 0000000000000..6b866be7d173f --- /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 `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 new file mode 100644 index 0000000000000..cf4d23656e0e1 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/nested.stderr @@ -0,0 +1,12 @@ +error[E0277]: `Bar` doesn't implement `Debug` + --> $DIR/nested.rs:15:22 + | +LL | println!("{:?}", bar()); + | ^^^^^ `Bar` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = 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 + +For more information about this error, try `rustc --explain E0277`. 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 + 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_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/no_revealing_outside_defining_module.stderr b/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr index 67752acb8c9af..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 @@ -5,12 +5,10 @@ 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` + found opaque type `Boo` error[E0308]: mismatched types --> $DIR/no_revealing_outside_defining_module.rs:19:5 @@ -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` + = 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/not_a_defining_use.rs b/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs index 107cd39457935..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 { - //~^ ERROR non-defining opaque type use in defining scope - (t, 4i8) -} - 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 08e49845521c6..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:10:27 - | -LL | fn two(t: T) -> Two { - | ^^^^^^^^^^^ - | -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`. 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..dc7054da5ec19 --- /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 `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 new file mode 100644 index 0000000000000..6997676260dd6 --- /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 `Foo` + --> $DIR/self-referential-2.rs:7:5 + | +LL | 42_i32 + | ^^^^^^ no implementation for `i32 == Foo` + | + = 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-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 new file mode 100644 index 0000000000000..4974ac72dad18 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/self-referential.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, '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() { + let meh = 42; + let muh = 69; + assert_eq!(bar(&meh), bar(&meh)); +} diff --git a/src/test/ui/type-alias-impl-trait/self-referential.stderr b/src/test/ui/type-alias-impl-trait/self-referential.stderr new file mode 100644 index 0000000000000..0626e6be0d5a5 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/self-referential.stderr @@ -0,0 +1,27 @@ +error[E0277]: can't compare `&i32` with `Bar<'b, 'a>` + --> $DIR/self-referential.rs:6:5 + | +LL | i + | ^ no implementation for `&i32 == Bar<'b, 'a>` + | + = help: the trait `PartialEq>` is not implemented for `&i32` + +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/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..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 @@ -11,9 +11,9 @@ 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 + //~^ `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 73558d39ad561..c8825c68e33cc 100644 --- a/src/test/ui/type-alias-impl-trait/structural-match.rs +++ b/src/test/ui/type-alias-impl-trait/structural-match.rs @@ -12,9 +12,9 @@ const fn value() -> Foo { const VALUE: Foo = value(); fn test() { - match todo!() { + 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-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-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 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..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 @@ -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 `Foo`, 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 `Foo`, 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),