diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 692f39368243a..ca7a64e254e14 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -247,12 +247,7 @@ impl<'hir> LoweringContext<'_, 'hir> { AnonymousLifetimeMode::PassThrough, |this, idty| { let ret_id = asyncness.opt_return_id(); - this.lower_fn_decl( - &decl, - Some((fn_def_id.to_def_id(), idty)), - true, - ret_id, - ) + this.lower_fn_decl(&decl, Some((fn_def_id, idty)), true, ret_id) }, ); let sig = hir::FnSig { @@ -1264,7 +1259,7 @@ impl<'hir> LoweringContext<'_, 'hir> { |this, idty| { this.lower_fn_decl( &sig.decl, - Some((fn_def_id.to_def_id(), idty)), + Some((fn_def_id, idty)), impl_trait_return_allow, is_async, ) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index d0fbc2d0f11d4..c04b0471cb72f 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -228,7 +228,7 @@ enum ImplTraitContext<'b, 'a> { ReturnPositionOpaqueTy { /// `DefId` for the parent function, used to look up necessary /// information later. - fn_def_id: DefId, + fn_def_id: LocalDefId, /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn, origin: hir::OpaqueTyOrigin, }, @@ -646,31 +646,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// parameter while `f` is running (and restored afterwards). fn collect_in_band_defs( &mut self, - parent_def_id: LocalDefId, - anonymous_lifetime_mode: AnonymousLifetimeMode, - f: impl FnOnce(&mut Self) -> (Vec>, T), - ) -> (Vec>, T) { - assert!(!self.is_collecting_in_band_lifetimes); - assert!(self.lifetimes_to_define.is_empty()); - let old_anonymous_lifetime_mode = self.anonymous_lifetime_mode; - - self.anonymous_lifetime_mode = anonymous_lifetime_mode; - self.is_collecting_in_band_lifetimes = true; - - let (in_band_ty_params, res) = f(self); - - self.is_collecting_in_band_lifetimes = false; - self.anonymous_lifetime_mode = old_anonymous_lifetime_mode; - - let lifetimes_to_define = self.lifetimes_to_define.split_off(0); + f: impl FnOnce(&mut Self) -> T, + ) -> (Vec<(Span, ParamName)>, T) { + let was_collecting = std::mem::replace(&mut self.is_collecting_in_band_lifetimes, true); + let len = self.lifetimes_to_define.len(); - let params = lifetimes_to_define - .into_iter() - .map(|(span, hir_name)| self.lifetime_to_generic_param(span, hir_name, parent_def_id)) - .chain(in_band_ty_params.into_iter()) - .collect(); + let res = f(self); - (params, res) + let lifetimes_to_define = self.lifetimes_to_define.split_off(len); + self.is_collecting_in_band_lifetimes = was_collecting; + (lifetimes_to_define, res) } /// Converts a lifetime into a new generic parameter. @@ -785,27 +770,39 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { anonymous_lifetime_mode: AnonymousLifetimeMode, f: impl FnOnce(&mut Self, &mut Vec>) -> T, ) -> (hir::Generics<'hir>, T) { - let (in_band_defs, (mut lowered_generics, res)) = - self.with_in_scope_lifetime_defs(&generics.params, |this| { - this.collect_in_band_defs(parent_def_id, anonymous_lifetime_mode, |this| { - let mut params = Vec::new(); - // Note: it is necessary to lower generics *before* calling `f`. - // When lowering `async fn`, there's a final step when lowering - // the return type that assumes that all in-scope lifetimes have - // already been added to either `in_scope_lifetimes` or - // `lifetimes_to_define`. If we swapped the order of these two, - // in-band-lifetimes introduced by generics or where-clauses - // wouldn't have been added yet. - let generics = this.lower_generics_mut( - generics, - ImplTraitContext::Universal(&mut params, this.current_hir_id_owner), - ); - let res = f(this, &mut params); - (params, (generics, res)) + let (lifetimes_to_define, (mut lowered_generics, impl_trait_defs, res)) = self + .collect_in_band_defs(|this| { + this.with_anonymous_lifetime_mode(anonymous_lifetime_mode, |this| { + this.with_in_scope_lifetime_defs(&generics.params, |this| { + let mut impl_trait_defs = Vec::new(); + // Note: it is necessary to lower generics *before* calling `f`. + // When lowering `async fn`, there's a final step when lowering + // the return type that assumes that all in-scope lifetimes have + // already been added to either `in_scope_lifetimes` or + // `lifetimes_to_define`. If we swapped the order of these two, + // in-band-lifetimes introduced by generics or where-clauses + // wouldn't have been added yet. + let generics = this.lower_generics_mut( + generics, + ImplTraitContext::Universal( + &mut impl_trait_defs, + this.current_hir_id_owner, + ), + ); + let res = f(this, &mut impl_trait_defs); + (generics, impl_trait_defs, res) + }) }) }); - lowered_generics.params.extend(in_band_defs); + lowered_generics.params.extend( + lifetimes_to_define + .into_iter() + .map(|(span, hir_name)| { + self.lifetime_to_generic_param(span, hir_name, parent_def_id) + }) + .chain(impl_trait_defs), + ); let lowered_generics = lowered_generics.into_generics(self.arena); (lowered_generics, res) @@ -1380,7 +1377,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_opaque_impl_trait( &mut self, span: Span, - fn_def_id: Option, + fn_def_id: Option, origin: hir::OpaqueTyOrigin, opaque_ty_node_id: NodeId, capturable_lifetimes: Option<&FxHashSet>, @@ -1452,7 +1449,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: lctx.lower_span(span), }, bounds: hir_bounds, - impl_trait_fn: fn_def_id, origin, }; @@ -1522,7 +1518,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_fn_decl( &mut self, decl: &FnDecl, - mut in_band_ty_params: Option<(DefId, &mut Vec>)>, + mut in_band_ty_params: Option<(LocalDefId, &mut Vec>)>, impl_trait_return_allow: bool, make_ret_async: Option, ) -> &'hir hir::FnDecl<'hir> { @@ -1580,7 +1576,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { Some((def_id, _)) if impl_trait_return_allow => { ImplTraitContext::ReturnPositionOpaqueTy { fn_def_id: def_id, - origin: hir::OpaqueTyOrigin::FnReturn, + origin: hir::OpaqueTyOrigin::FnReturn(def_id), } } _ => ImplTraitContext::disallowed(), @@ -1635,7 +1631,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_async_fn_ret_ty( &mut self, output: &FnRetTy, - fn_def_id: DefId, + fn_def_id: LocalDefId, opaque_ty_node_id: NodeId, ) -> hir::FnRetTy<'hir> { debug!( @@ -1689,18 +1685,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // this is because the elided lifetimes from the return type // should be figured out using the ordinary elision rules, and // this desugaring achieves that. + + debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", self.in_scope_lifetimes); + debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", self.lifetimes_to_define); + + // Calculate all the lifetimes that should be captured + // by the opaque type. This should include all in-scope + // lifetime parameters, including those defined in-band. // - // The variable `input_lifetimes_count` tracks the number of - // lifetime parameters to the opaque type *not counting* those - // lifetimes elided in the return type. This includes those - // that are explicitly declared (`in_scope_lifetimes`) and - // those elided lifetimes we found in the arguments (current - // content of `lifetimes_to_define`). Next, we will process - // the return type, which will cause `lifetimes_to_define` to - // grow. - let input_lifetimes_count = self.in_scope_lifetimes.len() + self.lifetimes_to_define.len(); - - let mut lifetime_params = Vec::new(); + // `lifetime_params` is a vector of tuple (span, parameter name, lifetime name). + + // Input lifetime like `'a` or `'1`: + let mut lifetime_params: Vec<_> = self + .in_scope_lifetimes + .iter() + .cloned() + .map(|name| (name.ident().span, name, hir::LifetimeName::Param(name))) + .chain( + self.lifetimes_to_define + .iter() + .map(|&(span, name)| (span, name, hir::LifetimeName::Param(name))), + ) + .collect(); + self.with_hir_id_owner(opaque_ty_node_id, |this| { // We have to be careful to get elision right here. The // idea is that we create a lifetime parameter for each @@ -1710,34 +1717,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and // hence the elision takes place at the fn site. - let future_bound = this - .with_anonymous_lifetime_mode(AnonymousLifetimeMode::CreateParameter, |this| { - this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span) + let (lifetimes_to_define, future_bound) = + this.with_anonymous_lifetime_mode(AnonymousLifetimeMode::CreateParameter, |this| { + this.collect_in_band_defs(|this| { + this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span) + }) }); - debug!("lower_async_fn_ret_ty: future_bound={:#?}", future_bound); + debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", lifetimes_to_define); - // Calculate all the lifetimes that should be captured - // by the opaque type. This should include all in-scope - // lifetime parameters, including those defined in-band. - // - // Note: this must be done after lowering the output type, - // as the output type may introduce new in-band lifetimes. - lifetime_params = this - .in_scope_lifetimes - .iter() - .cloned() - .map(|name| (name.ident().span, name)) - .chain(this.lifetimes_to_define.iter().cloned()) - .collect(); - - debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", this.in_scope_lifetimes); - debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", this.lifetimes_to_define); + lifetime_params.extend( + // Output lifetime like `'_`: + lifetimes_to_define + .into_iter() + .map(|(span, name)| (span, name, hir::LifetimeName::Implicit(false))), + ); debug!("lower_async_fn_ret_ty: lifetime_params={:#?}", lifetime_params); let generic_params = - this.arena.alloc_from_iter(lifetime_params.iter().map(|(span, hir_name)| { - this.lifetime_to_generic_param(*span, *hir_name, opaque_ty_def_id) + this.arena.alloc_from_iter(lifetime_params.iter().map(|&(span, hir_name, _)| { + this.lifetime_to_generic_param(span, hir_name, opaque_ty_def_id) })); let opaque_ty_item = hir::OpaqueTy { @@ -1747,8 +1746,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: this.lower_span(span), }, bounds: arena_vec![this; future_bound], - impl_trait_fn: Some(fn_def_id), - origin: hir::OpaqueTyOrigin::AsyncFn, + origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id), }; trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id); @@ -1771,25 +1769,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // For the "output" lifetime parameters, we just want to // generate `'_`. - let mut generic_args = Vec::with_capacity(lifetime_params.len()); - generic_args.extend(lifetime_params[..input_lifetimes_count].iter().map( - |&(span, hir_name)| { - // Input lifetime like `'a` or `'1`: + let generic_args = + self.arena.alloc_from_iter(lifetime_params.into_iter().map(|(span, _, name)| { GenericArg::Lifetime(hir::Lifetime { hir_id: self.next_id(), span: self.lower_span(span), - name: hir::LifetimeName::Param(hir_name), + name, }) - }, - )); - generic_args.extend(lifetime_params[input_lifetimes_count..].iter().map(|&(span, _)| - // Output lifetime like `'_`. - GenericArg::Lifetime(hir::Lifetime { - hir_id: self.next_id(), - span: self.lower_span(span), - name: hir::LifetimeName::Implicit(false), - }))); - let generic_args = self.arena.alloc_from_iter(generic_args); + })); // Create the `Foo<...>` reference itself. Note that the `type // Foo = impl Trait` is, internally, created as a child of the @@ -1805,7 +1792,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_async_fn_output_type_to_future_bound( &mut self, output: &FnRetTy, - fn_def_id: DefId, + fn_def_id: LocalDefId, span: Span, ) -> hir::GenericBound<'hir> { // Compute the `T` in `Future` from the return type. @@ -1816,7 +1803,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // generates. let context = ImplTraitContext::ReturnPositionOpaqueTy { fn_def_id, - origin: hir::OpaqueTyOrigin::FnReturn, + origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), }; self.lower_ty(ty, context) } @@ -2453,17 +2440,12 @@ impl<'hir> GenericArgsCtor<'hir> { } } +#[tracing::instrument(level = "debug")] fn lifetimes_from_impl_trait_bounds( opaque_ty_id: NodeId, bounds: hir::GenericBounds<'_>, lifetimes_to_include: Option<&FxHashSet>, ) -> Vec<(hir::LifetimeName, Span)> { - debug!( - "lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \ - bounds={:#?})", - opaque_ty_id, bounds, - ); - // This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that // appear in the bounds, excluding lifetimes that are created within the bounds. // E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`. diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 4eb7be542e7a1..76b3be7976c61 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -173,7 +173,7 @@ fn check_opaque_type_parameter_valid( // fn foo() -> foo::<'static..'static>::Foo<'l0..'lm>. // // which would error here on all of the `'static` args. - OpaqueTyOrigin::FnReturn | OpaqueTyOrigin::AsyncFn => return true, + OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return true, // Check these OpaqueTyOrigin::TyAlias => {} } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 487ae87052ba3..d393ea6893849 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2248,7 +2248,6 @@ pub struct BareFnTy<'hir> { pub struct OpaqueTy<'hir> { pub generics: Generics<'hir>, pub bounds: GenericBounds<'hir>, - pub impl_trait_fn: Option, pub origin: OpaqueTyOrigin, } @@ -2256,9 +2255,9 @@ pub struct OpaqueTy<'hir> { #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub enum OpaqueTyOrigin { /// `-> impl Trait` - FnReturn, + FnReturn(LocalDefId), /// `async fn` - AsyncFn, + AsyncFn(LocalDefId), /// type aliases: `type Foo = impl Trait;` TyAlias, } @@ -2809,7 +2808,9 @@ impl ItemKind<'_> { Some(match *self { ItemKind::Fn(_, ref generics, _) | ItemKind::TyAlias(_, ref generics) - | ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. }) + | ItemKind::OpaqueTy(OpaqueTy { + ref generics, origin: OpaqueTyOrigin::TyAlias, .. + }) | ItemKind::Enum(_, ref generics) | ItemKind::Struct(_, ref generics) | ItemKind::Union(_, ref generics) diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 32c02033dc9b9..9cf6cde259150 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -1,6 +1,5 @@ use crate::infer::type_variable::TypeVariableOriginKind; -use crate::infer::InferCtxt; -use crate::rustc_middle::ty::TypeFoldable; +use crate::infer::{InferCtxt, Symbol}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace}; @@ -11,7 +10,7 @@ use rustc_middle::hir::map::Map; use rustc_middle::infer::unify_key::ConstVariableOriginKind; use rustc_middle::ty::print::Print; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; -use rustc_middle::ty::{self, DefIdTree, InferConst, Ty, TyCtxt}; +use rustc_middle::ty::{self, Const, DefIdTree, InferConst, Ty, TyCtxt, TypeFoldable, TypeFolder}; use rustc_span::symbol::kw; use rustc_span::Span; use std::borrow::Cow; @@ -306,6 +305,15 @@ pub enum UnderspecifiedArgKind { Const { is_parameter: bool }, } +impl UnderspecifiedArgKind { + fn descr(&self) -> &'static str { + match self { + Self::Type { .. } => "type", + Self::Const { .. } => "const", + } + } +} + impl InferenceDiagnosticsData { /// Generate a label for a generic argument which can't be inferred. When not /// much is known about the argument, `use_diag` may be used to describe the @@ -588,6 +596,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } + let param_type = arg_data.kind.descr(); let suffix = match local_visitor.found_node_ty { Some(ty) if ty.is_closure() => { let substs = @@ -626,13 +635,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } Some(ty) if is_named_and_not_impl_trait(ty) && arg_data.name == "_" => { let ty = ty_to_string(ty); - format!("the explicit type `{}`, with the type parameters specified", ty) + format!("the explicit type `{}`, with the {} parameters specified", ty, param_type) } Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != arg_data.name => { + let ty = ResolvedTypeParamEraser::new(self.tcx).fold_ty(ty); + let ty = ErrTypeParamEraser(self.tcx).fold_ty(ty); let ty = ty_to_string(ty); format!( - "the explicit type `{}`, where the type parameter `{}` is specified", - ty, arg_data.name, + "the explicit type `{}`, where the {} parameter `{}` is specified", + ty, param_type, arg_data.name, ) } _ => "a type".to_string(), @@ -908,3 +919,117 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err } } + +/// Turn *resolved* type params into `[type error]` to signal we don't want to display them. After +/// performing that replacement, we'll turn all remaining infer type params to use their name from +/// their definition, and replace all the `[type error]`s back to being infer so they display in +/// the output as `_`. If we didn't go through `[type error]`, we would either show all type params +/// by their name *or* `_`, neither of which is desireable: we want to show all types that we could +/// infer as `_` to reduce verbosity and avoid telling the user about unnecessary type annotations. +struct ResolvedTypeParamEraser<'tcx> { + tcx: TyCtxt<'tcx>, + level: usize, +} + +impl<'tcx> ResolvedTypeParamEraser<'tcx> { + fn new(tcx: TyCtxt<'tcx>) -> Self { + ResolvedTypeParamEraser { tcx, level: 0 } + } + + /// Replace not yet inferred const params with their def name. + fn replace_infers(&self, c: &'tcx Const<'tcx>, index: u32, name: Symbol) -> &'tcx Const<'tcx> { + match c.val { + ty::ConstKind::Infer(..) => self.tcx().mk_const_param(index, name, c.ty), + _ => c, + } + } +} + +impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + self.tcx + } + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + self.level += 1; + let t = match t.kind() { + // We'll hide this type only if all its type params are hidden as well. + ty::Adt(def, substs) => { + let generics = self.tcx().generics_of(def.did); + // Account for params with default values, like `Vec`, where we + // want to show `Vec`, not `Vec`. If we replaced that + // subst, then we'd get the incorrect output, so we passthrough. + let substs: Vec<_> = substs + .iter() + .zip(generics.params.iter()) + .map(|(subst, param)| match &(subst.unpack(), ¶m.kind) { + (_, ty::GenericParamDefKind::Type { has_default: true, .. }) => subst, + (crate::infer::GenericArgKind::Const(c), _) => { + self.replace_infers(c, param.index, param.name).into() + } + _ => subst.super_fold_with(self), + }) + .collect(); + let should_keep = |subst: &GenericArg<'_>| match subst.unpack() { + ty::subst::GenericArgKind::Type(t) => match t.kind() { + ty::Error(_) => false, + _ => true, + }, + // Account for `const` params here, otherwise `doesnt_infer.rs` + // shows `_` instead of `Foo<{ _: u32 }>` + ty::subst::GenericArgKind::Const(_) => true, + _ => false, + }; + if self.level == 1 || substs.iter().any(should_keep) { + let substs = self.tcx().intern_substs(&substs[..]); + self.tcx().mk_ty(ty::Adt(def, substs)) + } else { + self.tcx().ty_error() + } + } + ty::Ref(_, ty, _) => { + let ty = self.fold_ty(ty); + match ty.kind() { + // Avoid `&_`, these can be safely presented as `_`. + ty::Error(_) => self.tcx().ty_error(), + _ => t.super_fold_with(self), + } + } + // We could account for `()` if we wanted to replace it, but it's assured to be short. + ty::Tuple(_) + | ty::Slice(_) + | ty::RawPtr(_) + | ty::FnDef(..) + | ty::FnPtr(_) + | ty::Opaque(..) + | ty::Projection(_) + | ty::Never => t.super_fold_with(self), + ty::Array(ty, c) => self + .tcx() + .mk_ty(ty::Array(self.fold_ty(ty), self.replace_infers(c, 0, Symbol::intern("N")))), + // We don't want to hide type params that haven't been resolved yet. + // This would be the type that will be written out with the type param + // name in the output. + ty::Infer(_) => t, + // We don't want to hide the outermost type, only its type params. + _ if self.level == 1 => t.super_fold_with(self), + // Hide this type + _ => self.tcx().ty_error(), + }; + self.level -= 1; + t + } +} + +/// Replace `[type error]` with `ty::Infer(ty::Var)` to display `_`. +struct ErrTypeParamEraser<'tcx>(TyCtxt<'tcx>); +impl<'tcx> TypeFolder<'tcx> for ErrTypeParamEraser<'tcx> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + self.0 + } + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + match t.kind() { + ty::Error(_) => self.tcx().mk_ty_var(ty::TyVid::from_u32(0)), + _ => t.super_fold_with(self), + } + } +} diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs index 90bc5b3b2fed1..04eceecc5f072 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs @@ -107,7 +107,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, - origin: hir::OpaqueTyOrigin::AsyncFn, + origin: hir::OpaqueTyOrigin::AsyncFn(..), .. }), .. diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index d9ab4ae1eda29..c2ef0b41e27bf 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -276,7 +276,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { debug!(?concrete_ty); let first_own_region = match opaque_defn.origin { - hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => { + hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => { // We lower // // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm> @@ -461,35 +461,29 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { if let Some(def_id) = def_id.as_local() { let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let parent_def_id = self.infcx.defining_use_anchor; - let (in_definition_scope, origin) = match tcx.hir().expect_item(def_id).kind - { + let item_kind = &tcx.hir().expect_item(def_id).kind; + let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item_kind else { + span_bug!( + self.value_span, + "weird opaque type: {:#?}, {:#?}", + ty.kind(), + item_kind + ) + }; + let in_definition_scope = match *origin { + // Async `impl Trait` + hir::OpaqueTyOrigin::AsyncFn(parent) => parent == parent_def_id, // Anonymous `impl Trait` - hir::ItemKind::OpaqueTy(hir::OpaqueTy { - impl_trait_fn: Some(parent), - origin, - .. - }) => (parent == parent_def_id.to_def_id(), origin), + hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id, // Named `type Foo = impl Bar;` - hir::ItemKind::OpaqueTy(hir::OpaqueTy { - impl_trait_fn: None, - origin, - .. - }) => { - (may_define_opaque_type(tcx, parent_def_id, opaque_hir_id), origin) - } - ref itemkind => { - span_bug!( - self.value_span, - "weird opaque type: {:#?}, {:#?}", - ty.kind(), - itemkind - ) + hir::OpaqueTyOrigin::TyAlias => { + may_define_opaque_type(tcx, parent_def_id, opaque_hir_id) } }; if in_definition_scope { let opaque_type_key = OpaqueTypeKey { def_id: def_id.to_def_id(), substs }; - return self.fold_opaque_ty(ty, opaque_type_key, origin); + return self.fold_opaque_ty(ty, opaque_type_key, *origin); } debug!( diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 7e1804673df2c..fd1409949f0a7 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2055,13 +2055,17 @@ impl<'tcx> TyCtxt<'tcx> { } } -/// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition. -pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option { - if let Some(def_id) = def_id.as_local() { - if let Node::Item(item) = tcx.hir().get(tcx.hir().local_def_id_to_hir_id(def_id)) { - if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind { - return opaque_ty.impl_trait_fn; - } +/// Yields the parent function's `LocalDefId` if `def_id` is an `impl Trait` definition. +pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + let def_id = def_id.as_local()?; + if let Node::Item(item) = tcx.hir().get(tcx.hir().local_def_id_to_hir_id(def_id)) { + if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind { + return match opaque_ty.origin { + hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => { + Some(parent) + } + hir::OpaqueTyOrigin::TyAlias => None, + }; } } None diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 1ff33689b53c7..c94c56df75b78 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -968,7 +968,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let (generics, bounds) = match opaque_ty.kind { // Named opaque `impl Trait` types are reached via `TyKind::Path`. // This arm is for `impl Trait` in the types of statics, constants and locals. - hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: None, .. }) => { + hir::ItemKind::OpaqueTy(hir::OpaqueTy { + origin: hir::OpaqueTyOrigin::TyAlias, + .. + }) => { intravisit::walk_ty(self, ty); // Elided lifetimes are not allowed in non-return @@ -985,7 +988,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } // RPIT (return position impl trait) hir::ItemKind::OpaqueTy(hir::OpaqueTy { - impl_trait_fn: Some(_), + origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..), ref generics, bounds, .. @@ -1695,7 +1698,11 @@ fn compute_object_lifetime_defaults( hir::ItemKind::Struct(_, ref generics) | hir::ItemKind::Union(_, ref generics) | hir::ItemKind::Enum(_, ref generics) - | hir::ItemKind::OpaqueTy(hir::OpaqueTy { ref generics, impl_trait_fn: None, .. }) + | hir::ItemKind::OpaqueTy(hir::OpaqueTy { + ref generics, + origin: hir::OpaqueTyOrigin::TyAlias, + .. + }) | hir::ItemKind::TyAlias(_, ref generics) | hir::ItemKind::Trait(_, _, ref generics, ..) => { let result = object_lifetime_defaults_for_item(tcx, generics); @@ -2067,7 +2074,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .. }) = self.tcx.hir().get(parent_hir_id) { - if opaque.origin != hir::OpaqueTyOrigin::AsyncFn { + if !matches!(opaque.origin, hir::OpaqueTyOrigin::AsyncFn(..)) { continue 'lifetimes; } // We want to do this only if the liftime identifier is already defined diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 711a6f2fbebdd..74a015d4c348e 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -248,7 +248,7 @@ fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option { fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { // The param_env of an impl Trait type is its defining function's param_env if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) { - return param_env(tcx, parent); + return param_env(tcx, parent.to_def_id()); } // Compute the bounds on Self and the type parameters. @@ -313,7 +313,7 @@ fn well_formed_types_in_env<'tcx>( // The environment of an impl Trait type is its defining function's environment. if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) { - return well_formed_types_in_env(tcx, parent); + return well_formed_types_in_env(tcx, parent.to_def_id()); } // Compute the bounds on `Self` and the type parameters. diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 08261fedd4a25..908adeb22b364 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2336,9 +2336,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let def_id = item_id.def_id.to_def_id(); match opaque_ty.kind { - hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => { - self.impl_trait_ty_to_ty(def_id, lifetimes, impl_trait_fn.is_some()) - } + hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => self + .impl_trait_ty_to_ty( + def_id, + lifetimes, + matches!( + origin, + hir::OpaqueTyOrigin::FnReturn(..) + | hir::OpaqueTyOrigin::AsyncFn(..) + ), + ), ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i), } } diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 2061f955d968f..a6b16e7f0d4d8 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -541,7 +541,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( } if let ItemKind::OpaqueTy(hir::OpaqueTy { - origin: hir::OpaqueTyOrigin::AsyncFn | hir::OpaqueTyOrigin::FnReturn, + origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..), .. }) = item.kind { @@ -567,7 +567,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( visitor.visit_item(&item); let is_async = match item.kind { ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => { - matches!(origin, hir::OpaqueTyOrigin::AsyncFn) + matches!(origin, hir::OpaqueTyOrigin::AsyncFn(..)) } _ => unreachable!(), }; @@ -604,7 +604,7 @@ pub(super) fn check_opaque_for_cycles<'tcx>( ) -> Result<(), ErrorReported> { if tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs).is_err() { match origin { - hir::OpaqueTyOrigin::AsyncFn => async_opaque_type_cycle_error(tcx, span), + hir::OpaqueTyOrigin::AsyncFn(..) => async_opaque_type_cycle_error(tcx, span), _ => opaque_type_cycle_error(tcx, def_id, span), } Err(ErrorReported) @@ -635,7 +635,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(..) => return, // Can have different predicates to their defining use hir::OpaqueTyOrigin::TyAlias => {} } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 67a3053c60786..e8d28dd75d6aa 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -594,7 +594,11 @@ fn type_param_predicates( ItemKind::Fn(.., ref generics, _) | ItemKind::Impl(hir::Impl { ref generics, .. }) | ItemKind::TyAlias(_, ref generics) - | ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. }) + | ItemKind::OpaqueTy(OpaqueTy { + ref generics, + origin: hir::OpaqueTyOrigin::TyAlias, + .. + }) | ItemKind::Enum(_, ref generics) | ItemKind::Struct(_, ref generics) | ItemKind::Union(_, ref generics) => generics, @@ -793,7 +797,10 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { } // Desugared from `impl Trait`, so visited by the function's return type. - hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(_), .. }) => {} + hir::ItemKind::OpaqueTy(hir::OpaqueTy { + origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..), + .. + }) => {} // Don't call `type_of` on opaque types, since that depends on type // checking function bodies. `check_item_type` ensures that it's called @@ -1488,15 +1495,18 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { Some(tcx.typeck_root_def_id(def_id)) } Node::Item(item) => match item.kind { - ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => { - impl_trait_fn.or_else(|| { - let parent_id = tcx.hir().get_parent_item(hir_id); - assert!(parent_id != hir_id && parent_id != CRATE_HIR_ID); - debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id); - // Opaque types are always nested within another item, and - // inherit the generics of the item. - Some(tcx.hir().local_def_id(parent_id).to_def_id()) - }) + ItemKind::OpaqueTy(hir::OpaqueTy { + origin: + hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id), + .. + }) => Some(fn_def_id.to_def_id()), + ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { + let parent_id = tcx.hir().get_parent_item(hir_id); + assert!(parent_id != hir_id && parent_id != CRATE_HIR_ID); + debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id); + // Opaque types are always nested within another item, and + // inherit the generics of the item. + Some(tcx.hir().local_def_id(parent_id).to_def_id()) } _ => None, }, @@ -2051,31 +2061,32 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP generics } ItemKind::OpaqueTy(OpaqueTy { - bounds: _, - impl_trait_fn, + origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..), + .. + }) => { + // return-position impl trait + // + // We don't inherit predicates from the parent here: + // If we have, say `fn f<'a, T: 'a>() -> impl Sized {}` + // then the return type is `f::<'static, T>::{{opaque}}`. + // + // If we inherited the predicates of `f` then we would + // require that `T: 'static` to show that the return + // type is well-formed. + // + // The only way to have something with this opaque type + // is from the return type of the containing function, + // which will ensure that the function's predicates + // hold. + return ty::GenericPredicates { parent: None, predicates: &[] }; + } + ItemKind::OpaqueTy(OpaqueTy { ref generics, - origin: _, + origin: hir::OpaqueTyOrigin::TyAlias, + .. }) => { - if impl_trait_fn.is_some() { - // return-position impl trait - // - // We don't inherit predicates from the parent here: - // If we have, say `fn f<'a, T: 'a>() -> impl Sized {}` - // then the return type is `f::<'static, T>::{{opaque}}`. - // - // If we inherited the predicates of `f` then we would - // require that `T: 'static` to show that the return - // type is well-formed. - // - // The only way to have something with this opaque type - // is from the return type of the containing function, - // which will ensure that the function's predicates - // hold. - return ty::GenericPredicates { parent: None, predicates: &[] }; - } else { - // type-alias impl trait - generics - } + // type-alias impl trait + generics } _ => NO_GENERICS, diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index b684844744de3..af199ca99460f 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -394,13 +394,13 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); tcx.mk_adt(def, substs) } - ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => { + ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { find_opaque_ty_constraints(tcx, def_id) } // Opaque types desugared from `impl Trait`. - ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: Some(owner), .. }) => { + ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), .. }) => { let concrete_ty = tcx - .mir_borrowck(owner.expect_local()) + .mir_borrowck(owner) .concrete_opaque_types .get_value_matching(|(key, _)| key.def_id == def_id.to_def_id()) .copied() @@ -413,7 +413,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { ), ); if let Some(ErrorReported) = - tcx.typeck(owner.expect_local()).tainted_by_errors + tcx.typeck(owner).tainted_by_errors { // Some error in the // owner fn prevented us from populating diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index e139ac8581e72..1691de93bdda2 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -296,7 +296,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl let (short, name) = item_ty_to_strs(myty.unwrap()); write!( w, - "

\ + "

\ {name}\

\n{}", ITEM_TABLE_OPEN, diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index f4f654f474526..dea6d08396f31 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -219,7 +219,7 @@ a { a.srclink, a#toggle-all-docs, a.anchor, -.section-header a, +.small-section-header a, #source-sidebar a, pre.rust a, .sidebar a, diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index b10b802038029..6e2cbbecbf712 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -181,7 +181,7 @@ a { a.srclink, a#toggle-all-docs, a.anchor, -.section-header a, +.small-section-header a, #source-sidebar a, pre.rust a, .sidebar a, diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 97f32ac1f7de3..4bf411d459a35 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -176,7 +176,7 @@ a { a.srclink, a#toggle-all-docs, a.anchor, -.section-header a, +.small-section-header a, #source-sidebar a, pre.rust a, .sidebar a, diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index c2ea54abd2ea8..7c55d10836c45 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -4,32 +4,34 @@ (function() { // This mapping table should match the discriminants of // `rustdoc::html::item_type::ItemType` type in Rust. -var itemTypes = ["mod", - "externcrate", - "import", - "struct", - "enum", - "fn", - "type", - "static", - "trait", - "impl", - "tymethod", - "method", - "structfield", - "variant", - "macro", - "primitive", - "associatedtype", - "constant", - "associatedconstant", - "union", - "foreigntype", - "keyword", - "existential", - "attr", - "derive", - "traitalias"]; +var itemTypes = [ + "mod", + "externcrate", + "import", + "struct", + "enum", + "fn", + "type", + "static", + "trait", + "impl", + "tymethod", + "method", + "structfield", + "variant", + "macro", + "primitive", + "associatedtype", + "constant", + "associatedconstant", + "union", + "foreigntype", + "keyword", + "existential", + "attr", + "derive", + "traitalias", +]; // used for special search precedence var TY_PRIMITIVE = itemTypes.indexOf("primitive"); diff --git a/src/test/rustdoc-gui/headers-color.goml b/src/test/rustdoc-gui/headers-color.goml index 7002812bb62c4..03b10e3f78d43 100644 --- a/src/test/rustdoc-gui/headers-color.goml +++ b/src/test/rustdoc-gui/headers-color.goml @@ -18,7 +18,10 @@ goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.must_use assert-css: ("#method\.must_use", {"color": "rgb(197, 197, 197)", "background-color": "rgba(255, 236, 164, 0.06)"}, ALL) goto: file://|DOC_PATH|/test_docs/index.html -assert-css: (".section-header a", {"color": "rgb(197, 197, 197)"}, ALL) +assert-css: (".small-section-header a", {"color": "rgb(197, 197, 197)"}, ALL) + +goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html +assert-css: (".section-header a", {"color": "rgb(57, 175, 215)"}, ALL) // Dark theme local-storage: {"rustdoc-theme": "dark", "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false"} @@ -34,7 +37,10 @@ goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.must_use assert-css: ("#method\.must_use", {"color": "rgb(221, 221, 221)", "background-color": "rgb(73, 74, 61)"}, ALL) goto: file://|DOC_PATH|/test_docs/index.html -assert-css: (".section-header a", {"color": "rgb(221, 221, 221)"}, ALL) +assert-css: (".small-section-header a", {"color": "rgb(221, 221, 221)"}, ALL) + +goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html +assert-css: (".section-header a", {"color": "rgb(210, 153, 29)"}, ALL) // Light theme local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"} @@ -52,4 +58,7 @@ goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.must_use assert-css: ("#method\.must_use", {"color": "rgb(0, 0, 0)", "background-color": "rgb(253, 255, 211)"}, ALL) goto: file://|DOC_PATH|/test_docs/index.html -assert-css: (".section-header a", {"color": "rgb(0, 0, 0)"}, ALL) +assert-css: (".small-section-header a", {"color": "rgb(0, 0, 0)"}, ALL) + +goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html +assert-css: (".section-header a", {"color": "rgb(56, 115, 173)"}, ALL) diff --git a/src/test/ui/async-await/generics-and-bounds.rs b/src/test/ui/async-await/generics-and-bounds.rs index 963b19b34a620..90ab0c01f5450 100644 --- a/src/test/ui/async-await/generics-and-bounds.rs +++ b/src/test/ui/async-await/generics-and-bounds.rs @@ -2,6 +2,8 @@ // edition:2018 // compile-flags: --crate-type lib +#![feature(in_band_lifetimes)] + use std::future::Future; pub async fn simple_generic() {} @@ -71,6 +73,10 @@ pub fn call_with_ref_block<'a>(f: &'a (impl Foo + 'a)) -> impl Future impl Future + 'a { + async move { f.foo() } +} + pub fn async_block_with_same_generic_params_unifies() { let mut a = call_generic_bound_block(FooType); a = call_generic_bound_block(FooType); @@ -85,4 +91,9 @@ pub fn async_block_with_same_generic_params_unifies() { let f_two = FooType; let mut d = call_with_ref_block(&f_one); d = call_with_ref_block(&f_two); + + let f_one = FooType; + let f_two = FooType; + let mut d = call_with_ref_block_in_band(&f_one); + d = call_with_ref_block_in_band(&f_two); } diff --git a/src/test/ui/const-generics/defaults/doesnt_infer.stderr b/src/test/ui/const-generics/defaults/doesnt_infer.stderr index b57975e26f290..d6c64d58be5f3 100644 --- a/src/test/ui/const-generics/defaults/doesnt_infer.stderr +++ b/src/test/ui/const-generics/defaults/doesnt_infer.stderr @@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `Foo<{_: u32}>` LL | let foo = Foo::foo(); | --- ^^^^^^^^ cannot infer the value of const parameter `N` | | - | consider giving `foo` the explicit type `Foo<{_: u32}>`, where the type parameter `N` is specified + | consider giving `foo` the explicit type `Foo`, where the const parameter `N` is specified error: aborting due to previous error diff --git a/src/test/ui/inference/erase-type-params-in-label.rs b/src/test/ui/inference/erase-type-params-in-label.rs new file mode 100644 index 0000000000000..1fea2da92da94 --- /dev/null +++ b/src/test/ui/inference/erase-type-params-in-label.rs @@ -0,0 +1,27 @@ +fn main() { + let foo = foo(1, ""); //~ ERROR E0283 +} +fn baz() { + let bar = bar(1, ""); //~ ERROR E0283 +} + +struct Bar { + t: T, + k: K, + n: N, +} + +fn bar(t: T, k: K) -> Bar { + Bar { t, k, n: Default::default() } +} + +struct Foo { + t: T, + k: K, + n: N, + m: M, +} + +fn foo(t: T, k: K) -> Foo { + Foo { t, k, n: Default::default(), m: Default::default() } +} diff --git a/src/test/ui/inference/erase-type-params-in-label.stderr b/src/test/ui/inference/erase-type-params-in-label.stderr new file mode 100644 index 0000000000000..d0b06cde9d63a --- /dev/null +++ b/src/test/ui/inference/erase-type-params-in-label.stderr @@ -0,0 +1,41 @@ +error[E0283]: type annotations needed for `Foo` + --> $DIR/erase-type-params-in-label.rs:2:15 + | +LL | let foo = foo(1, ""); + | --- ^^^ cannot infer type for type parameter `W` declared on the function `foo` + | | + | consider giving `foo` the explicit type `Foo<_, _, W, Z>`, where the type parameter `W` is specified + | + = note: cannot satisfy `_: Default` +note: required by a bound in `foo` + --> $DIR/erase-type-params-in-label.rs:25:17 + | +LL | fn foo(t: T, k: K) -> Foo { + | ^^^^^^^ required by this bound in `foo` +help: consider specifying the type arguments in the function call + | +LL | let foo = foo::(1, ""); + | ++++++++++++++ + +error[E0283]: type annotations needed for `Bar` + --> $DIR/erase-type-params-in-label.rs:5:15 + | +LL | let bar = bar(1, ""); + | --- ^^^ cannot infer type for type parameter `Z` declared on the function `bar` + | | + | consider giving `bar` the explicit type `Bar<_, _, Z>`, where the type parameter `Z` is specified + | + = note: cannot satisfy `_: Default` +note: required by a bound in `bar` + --> $DIR/erase-type-params-in-label.rs:14:17 + | +LL | fn bar(t: T, k: K) -> Bar { + | ^^^^^^^ required by this bound in `bar` +help: consider specifying the type arguments in the function call + | +LL | let bar = bar::(1, ""); + | +++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/inference/issue-83606.stderr b/src/test/ui/inference/issue-83606.stderr index 65f3336b9358a..9ca8f35fd545a 100644 --- a/src/test/ui/inference/issue-83606.stderr +++ b/src/test/ui/inference/issue-83606.stderr @@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `[usize; _]` LL | let _ = foo("foo"); //<- Do not suggest `foo::("foo");`! | - ^^^ cannot infer the value of const parameter `N` declared on the function `foo` | | - | consider giving this pattern the explicit type `[usize; _]`, where the type parameter `N` is specified + | consider giving this pattern the explicit type `[_; N]`, where the const parameter `N` is specified error: aborting due to previous error diff --git a/src/test/ui/packed/packed-struct-drop-aligned.rs b/src/test/ui/packed/packed-struct-drop-aligned.rs index fab3bbedac667..b95cdbbbaad3b 100644 --- a/src/test/ui/packed/packed-struct-drop-aligned.rs +++ b/src/test/ui/packed/packed-struct-drop-aligned.rs @@ -1,6 +1,10 @@ // run-pass +#![feature(generators)] +#![feature(generator_trait)] use std::cell::Cell; use std::mem; +use std::ops::Generator; +use std::pin::Pin; struct Aligned<'a> { drop_count: &'a Cell @@ -19,15 +23,35 @@ impl<'a> Drop for Aligned<'a> { } } +#[repr(transparent)] +struct NotCopy(u8); + #[repr(packed)] -struct Packed<'a>(u8, Aligned<'a>); +struct Packed<'a>(NotCopy, Aligned<'a>); fn main() { let drop_count = &Cell::new(0); { - let mut p = Packed(0, Aligned { drop_count }); + let mut p = Packed(NotCopy(0), Aligned { drop_count }); p.1 = Aligned { drop_count }; assert_eq!(drop_count.get(), 1); } assert_eq!(drop_count.get(), 2); + + let drop_count = &Cell::new(0); + let mut g = || { + let mut p = Packed(NotCopy(0), Aligned { drop_count }); + let _ = &p; + p.1 = Aligned { drop_count }; + assert_eq!(drop_count.get(), 1); + // Test that a generator drop function moves a value from a packed + // struct to a separate local before dropping it. We move out the + // first field to generate and open drop for the second field. + drop(p.0); + yield; + }; + Pin::new(&mut g).resume(()); + assert_eq!(drop_count.get(), 1); + drop(g); + assert_eq!(drop_count.get(), 2); } diff --git a/src/tools/miri b/src/tools/miri index 81e59e6b92cf1..dadcbebfbd017 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 81e59e6b92cf1729aabbbbf09b81a81a03775d64 +Subproject commit dadcbebfbd017aac2358cf652a4bd71a91694edc