From a4a07e00ced90e076dbadd8b350db527bcc588bd Mon Sep 17 00:00:00 2001 From: Tobia Date: Mon, 1 Apr 2019 18:16:03 +0900 Subject: [PATCH 01/10] Replaced linear token counting macros with optimized implementation --- src/librustc/hir/map/definitions.rs | 12 ++++++++++-- src/libserialize/serialize.rs | 17 ++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 1006d813e65ed..c72edb6cc6d72 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -696,9 +696,17 @@ impl DefPathData { } } +/// Evaluates to the number of tokens passed to it. +/// +/// Logarithmic counting: every one or two recursive expansions, the number of +/// tokens to count is divided by two, instead of being reduced by one. +/// Therefore, the recursion depth is the binary logarithm of the number of +/// tokens to count, and the expanded tree is likewise very small. macro_rules! count { - () => (0usize); - ( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*)); + () => (0usize); + ($one:tt) => (1usize); + ($($pairs:tt $_p:tt)*) => (count!($($pairs)*) << 1usize); + ($odd:tt $($rest:tt)*) => (count!($($rest)*) | 1usize); } // We define the GlobalMetaDataKind enum with this macro because we want to diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index cf948078b08c5..d53891828f1c0 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -723,10 +723,17 @@ macro_rules! peel { ($name:ident, $($other:ident,)*) => (tuple! { $($other,)* }) } -/// Evaluates to the number of identifiers passed to it, for example: `count_idents!(a, b, c) == 3 -macro_rules! count_idents { - () => { 0 }; - ($_i:ident, $($rest:ident,)*) => { 1 + count_idents!($($rest,)*) } +/// Evaluates to the number of tokens passed to it. +/// +/// Logarithmic counting: every one or two recursive expansions, the number of +/// tokens to count is divided by two, instead of being reduced by one. +/// Therefore, the recursion depth is the binary logarithm of the number of +/// tokens to count, and the expanded tree is likewise very small. +macro_rules! count { + () => (0usize); + ($one:tt) => (1usize); + ($($pairs:tt $_p:tt)*) => (count!($($pairs)*) << 1usize); + ($odd:tt $($rest:tt)*) => (count!($($rest)*) | 1usize); } macro_rules! tuple { @@ -735,7 +742,7 @@ macro_rules! tuple { impl<$($name:Decodable),*> Decodable for ($($name,)*) { #[allow(non_snake_case)] fn decode(d: &mut D) -> Result<($($name,)*), D::Error> { - let len: usize = count_idents!($($name,)*); + let len: usize = count!($($name)*); d.read_tuple(len, |d| { let mut i = 0; let ret = ($(d.read_tuple_arg({ i+=1; i-1 }, |d| -> Result<$name, D::Error> { From ff7e044f570f2389092f3d077c92017e727fa111 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 3 Jun 2019 21:16:31 +0200 Subject: [PATCH 02/10] get rid of real_intrinsics module instead import intrinsics locally in their wrapper functions --- src/libcore/intrinsics.rs | 43 +++++++++++++++------------------------ 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 782a7ba455984..63ca8098a0931 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1298,30 +1298,10 @@ extern "rust-intrinsic" { pub fn nontemporal_store(ptr: *mut T, val: T); } -mod real_intrinsics { - extern "rust-intrinsic" { - /// Copies `count * size_of::()` bytes from `src` to `dst`. The source - /// and destination must *not* overlap. - /// For the full docs, see the stabilized wrapper [`copy_nonoverlapping`]. - /// - /// [`copy_nonoverlapping`]: ../../std/ptr/fn.copy_nonoverlapping.html - pub fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); - - /// Copies `count * size_of::()` bytes from `src` to `dst`. The source - /// and destination may overlap. - /// For the full docs, see the stabilized wrapper [`copy`]. - /// - /// [`copy`]: ../../std/ptr/fn.copy.html - pub fn copy(src: *const T, dst: *mut T, count: usize); - - /// Sets `count * size_of::()` bytes of memory starting at `dst` to - /// `val`. - /// For the full docs, see the stabilized wrapper [`write_bytes`]. - /// - /// [`write_bytes`]: ../../std/ptr/fn.write_bytes.html - pub fn write_bytes(dst: *mut T, val: u8, count: usize); - } -} +// Some functions are defined here because they accidentally got made +// available in this module on stable. See . +// (`transmute` also falls into this category, but it cannot be wrapped due to the +// check that `T` and `U` have the same size.) /// Copies `count * size_of::()` bytes from `src` to `dst`. The source /// and destination must *not* overlap. @@ -1409,7 +1389,10 @@ mod real_intrinsics { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { - real_intrinsics::copy_nonoverlapping(src, dst, count); + extern "rust-intrinsic" { + fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); + } + copy_nonoverlapping(src, dst, count); } /// Copies `count * size_of::()` bytes from `src` to `dst`. The source @@ -1466,7 +1449,10 @@ pub unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub unsafe fn copy(src: *const T, dst: *mut T, count: usize) { - real_intrinsics::copy(src, dst, count) + extern "rust-intrinsic" { + fn copy(src: *const T, dst: *mut T, count: usize); + } + copy(src, dst, count) } /// Sets `count * size_of::()` bytes of memory starting at `dst` to @@ -1544,5 +1530,8 @@ pub unsafe fn copy(src: *const T, dst: *mut T, count: usize) { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { - real_intrinsics::write_bytes(dst, val, count) + extern "rust-intrinsic" { + fn write_bytes(dst: *mut T, val: u8, count: usize); + } + write_bytes(dst, val, count) } From f1867c549754403ac305be8f22a9e93642b3e288 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 7 Jun 2019 10:18:03 +0100 Subject: [PATCH 03/10] Rename `infer_types` to `infer_args` --- src/librustc/hir/lowering.rs | 4 ++-- src/librustc/hir/mod.rs | 8 ++++---- src/librustc/hir/print.rs | 16 ++++++++-------- src/librustc_typeck/astconv.rs | 30 +++++++++++++++--------------- src/librustc_typeck/check/mod.rs | 8 ++++---- 5 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index d6ad335525c14..1b433c8da60b0 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2168,7 +2168,7 @@ impl<'a> LoweringContext<'a> { itctx: ImplTraitContext<'_>, explicit_owner: Option, ) -> hir::PathSegment { - let (mut generic_args, infer_types) = if let Some(ref generic_args) = segment.args { + let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args { let msg = "parenthesized type parameters may only be used with a `Fn` trait"; match **generic_args { GenericArgs::AngleBracketed(ref data) => { @@ -2305,7 +2305,7 @@ impl<'a> LoweringContext<'a> { Some(id), Some(self.lower_res(res)), generic_args, - infer_types, + infer_args, ) } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 2aaf5ec775d49..82b7dfd363f14 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -348,7 +348,7 @@ pub struct PathSegment { /// This only applies to expression and pattern paths, and /// out of those only the segments with no type parameters /// to begin with, e.g., `Vec::new` is `>::new::<..>`. - pub infer_types: bool, + pub infer_args: bool, } impl PathSegment { @@ -358,7 +358,7 @@ impl PathSegment { ident, hir_id: None, res: None, - infer_types: true, + infer_args: true, args: None, } } @@ -368,13 +368,13 @@ impl PathSegment { hir_id: Option, res: Option, args: GenericArgs, - infer_types: bool, + infer_args: bool, ) -> Self { PathSegment { ident, hir_id, res, - infer_types, + infer_args, args: if args.is_empty() { None } else { diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index c8615f0ed1b93..7b0a499fa5c66 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1196,7 +1196,7 @@ impl<'a> State<'a> { segment.with_generic_args(|generic_args| { if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() { - return self.print_generic_args(&generic_args, segment.infer_types, true); + return self.print_generic_args(&generic_args, segment.infer_args, true); } Ok(()) })?; @@ -1561,7 +1561,7 @@ impl<'a> State<'a> { if segment.ident.name != kw::PathRoot { self.print_ident(segment.ident)?; segment.with_generic_args(|generic_args| { - self.print_generic_args(generic_args, segment.infer_types, + self.print_generic_args(generic_args, segment.infer_args, colons_before_params) })?; } @@ -1574,7 +1574,7 @@ impl<'a> State<'a> { if segment.ident.name != kw::PathRoot { self.print_ident(segment.ident)?; segment.with_generic_args(|generic_args| { - self.print_generic_args(generic_args, segment.infer_types, false) + self.print_generic_args(generic_args, segment.infer_args, false) })?; } Ok(()) @@ -1602,7 +1602,7 @@ impl<'a> State<'a> { self.print_ident(segment.ident)?; segment.with_generic_args(|generic_args| { self.print_generic_args(generic_args, - segment.infer_types, + segment.infer_args, colons_before_params) })?; } @@ -1614,7 +1614,7 @@ impl<'a> State<'a> { self.print_ident(item_segment.ident)?; item_segment.with_generic_args(|generic_args| { self.print_generic_args(generic_args, - item_segment.infer_types, + item_segment.infer_args, colons_before_params) }) } @@ -1626,7 +1626,7 @@ impl<'a> State<'a> { self.print_ident(item_segment.ident)?; item_segment.with_generic_args(|generic_args| { self.print_generic_args(generic_args, - item_segment.infer_types, + item_segment.infer_args, colons_before_params) }) } @@ -1635,7 +1635,7 @@ impl<'a> State<'a> { fn print_generic_args(&mut self, generic_args: &hir::GenericArgs, - infer_types: bool, + infer_args: bool, colons_before_params: bool) -> io::Result<()> { if generic_args.parenthesized { @@ -1681,7 +1681,7 @@ impl<'a> State<'a> { // FIXME(eddyb): this would leak into error messages (e.g., // "non-exhaustive patterns: `Some::<..>(_)` not covered"). - if infer_types && false { + if infer_args && false { start_or_comma(self)?; self.s.word("..")?; } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 34f817ba570e7..bac4df927b66a 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -191,7 +191,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { span, def_id, generic_args, - item_segment.infer_types, + item_segment.infer_args, None, ) }); @@ -208,7 +208,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { seg: &hir::PathSegment, generics: &ty::Generics, ) -> bool { - let explicit = !seg.infer_types; + let explicit = !seg.infer_args; let impl_trait = generics.params.iter().any(|param| match param.kind { ty::GenericParamDefKind::Type { synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), .. @@ -259,7 +259,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { GenericArgPosition::Value }, def.parent.is_none() && def.has_self, // `has_self` - seg.infer_types || suppress_mismatch, // `infer_types` + seg.infer_args || suppress_mismatch, // `infer_args` ).0 } @@ -272,7 +272,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { args: &hir::GenericArgs, position: GenericArgPosition, has_self: bool, - infer_types: bool, + infer_args: bool, ) -> (bool, Option>) { // At this stage we are guaranteed that the generic arguments are in the correct order, e.g. // that lifetimes will proceed types. So it suffices to check the number of each generic @@ -414,7 +414,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { ); } // Note that type errors are currently be emitted *after* const errors. - if !infer_types + if !infer_args || arg_counts.types > param_counts.types - defaults.types - has_self as usize { check_kind_count( "type", @@ -511,7 +511,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } // Check whether this segment takes generic arguments and the user has provided any. - let (generic_args, infer_types) = args_for_def_id(def_id); + let (generic_args, infer_args) = args_for_def_id(def_id); let mut args = generic_args.iter().flat_map(|generic_args| generic_args.args.iter()) .peekable(); @@ -535,7 +535,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { | (GenericArg::Const(_), GenericParamDefKind::Lifetime) => { // We expected a lifetime argument, but got a type or const // argument. That means we're inferring the lifetimes. - substs.push(inferred_kind(None, param, infer_types)); + substs.push(inferred_kind(None, param, infer_args)); params.next(); } (_, _) => { @@ -556,7 +556,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { (None, Some(¶m)) => { // If there are fewer arguments than parameters, it means // we're inferring the remaining arguments. - substs.push(inferred_kind(Some(&substs), param, infer_types)); + substs.push(inferred_kind(Some(&substs), param, infer_args)); args.next(); params.next(); } @@ -592,7 +592,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { span: Span, def_id: DefId, generic_args: &'a hir::GenericArgs, - infer_types: bool, + infer_args: bool, self_ty: Option>) -> (SubstsRef<'tcx>, Vec>, Option>) { @@ -617,7 +617,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { &generic_args, GenericArgPosition::Type, has_self, - infer_types, + infer_args, ); let is_object = self_ty.map_or(false, |ty| { @@ -644,7 +644,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { self_ty.is_some(), self_ty, // Provide the generic args, and whether types should be inferred. - |_| (Some(generic_args), infer_types), + |_| (Some(generic_args), infer_args), // Provide substitutions for parameters for which (valid) arguments have been provided. |param, arg| { match (¶m.kind, arg) { @@ -661,11 +661,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } }, // Provide substitutions for parameters for which arguments are inferred. - |substs, param, infer_types| { + |substs, param, infer_args| { match param.kind { GenericParamDefKind::Lifetime => tcx.lifetimes.re_static.into(), GenericParamDefKind::Type { has_default, .. } => { - if !infer_types && has_default { + if !infer_args && has_default { // No type parameter provided, but a default exists. // If we are converting an object type, then the @@ -693,7 +693,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { .subst_spanned(tcx, substs.unwrap(), Some(span)) ).into() } - } else if infer_types { + } else if infer_args { // No type parameters were provided, we can infer all. if !default_needs_object_self(param) { self.ty_infer_for_def(param, span).into() @@ -880,7 +880,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { self.create_substs_for_ast_path(span, trait_def_id, generic_args, - trait_segment.infer_types, + trait_segment.infer_args, Some(self_ty)) }) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a111851aa3797..c66d5ff08c0b8 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5419,10 +5419,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if !infer_args_for_err.contains(&index) { // Check whether the user has provided generic arguments. if let Some(ref data) = segments[index].args { - return (Some(data), segments[index].infer_types); + return (Some(data), segments[index].infer_args); } } - return (None, segments[index].infer_types); + return (None, segments[index].infer_args); } (None, true) @@ -5443,13 +5443,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }, // Provide substitutions for parameters for which arguments are inferred. - |substs, param, infer_types| { + |substs, param, infer_args| { match param.kind { GenericParamDefKind::Lifetime => { self.re_infer(span, Some(param)).unwrap().into() } GenericParamDefKind::Type { has_default, .. } => { - if !infer_types && has_default { + if !infer_args && has_default { // If we have a default, then we it doesn't matter that we're not // inferring the type arguments: we provide the default where any // is missing. From 5377dea7fc8dc1f05ddc4c444fddf1994293bfeb Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 6 Jun 2019 01:55:09 +0100 Subject: [PATCH 04/10] Fix issue with const arg inference --- src/librustc_typeck/astconv.rs | 24 ++++++++++++++++++------ src/librustc_typeck/check/mod.rs | 19 ++++++++++++++++++- src/librustc_typeck/collect.rs | 20 ++++++++++++++++++-- src/librustc_typeck/error_codes.rs | 4 ++-- 4 files changed, 56 insertions(+), 11 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index bac4df927b66a..349c4e608c244 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -13,7 +13,7 @@ use crate::middle::resolve_lifetime as rl; use crate::namespace::Namespace; use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc::traits; -use rustc::ty::{self, DefIdTree, Ty, TyCtxt, ToPredicate, TypeFoldable}; +use rustc::ty::{self, DefIdTree, Ty, TyCtxt, Const, ToPredicate, TypeFoldable}; use rustc::ty::{GenericParamDef, GenericParamDefKind}; use rustc::ty::subst::{Kind, Subst, InternalSubsts, SubstsRef}; use rustc::ty::wf::object_region_bounds; @@ -61,6 +61,13 @@ pub trait AstConv<'gcx, 'tcx> { span: Span) -> Ty<'tcx> { self.ty_infer(span) } + /// What const should we use when a const is omitted? + fn ct_infer( + &self, + ty: Ty<'tcx>, + param: Option<&ty::GenericParamDef>, + span: Span, + ) -> &'tcx Const<'tcx>; /// Projecting an associated type from a (potentially) /// higher-ranked trait reference is more complicated, because of @@ -280,7 +287,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { let param_counts = def.own_counts(); let arg_counts = args.own_counts(); let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0; - let infer_consts = position != GenericArgPosition::Type && arg_counts.consts == 0; let mut defaults: ty::GenericParamCount = Default::default(); for param in &def.params { @@ -333,7 +339,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { offset ); // We enforce the following: `required` <= `provided` <= `permitted`. - // For kinds without defaults (i.e., lifetimes), `required == permitted`. + // For kinds without defaults (e.g.., lifetimes), `required == permitted`. // For other kinds (i.e., types), `permitted` may be greater than `required`. if required <= provided && provided <= permitted { return (reported_late_bound_region_err.unwrap_or(false), None); @@ -404,7 +410,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { ); } // FIXME(const_generics:defaults) - if !infer_consts || arg_counts.consts > param_counts.consts { + if !infer_args || arg_counts.consts > param_counts.consts { check_kind_count( "const", param_counts.consts, @@ -707,8 +713,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } GenericParamDefKind::Const => { // FIXME(const_generics:defaults) - // We've already errored above about the mismatch. - tcx.consts.err.into() + if infer_args { + // No const parameters were provided, we can infer all. + let ty = tcx.at(span).type_of(param.def_id); + self.ct_infer(ty, Some(param), span).into() + } else { + // We've already errored above about the mismatch. + tcx.consts.err.into() + } } } }, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c66d5ff08c0b8..acb0b73af886d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -100,11 +100,12 @@ use rustc_data_structures::indexed_vec::Idx; use rustc_target::spec::abi::Abi; use rustc::infer::opaque_types::OpaqueTypeDecl; use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc::middle::region; use rustc::mir::interpret::{ConstValue, GlobalId}; use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine}; use rustc::ty::{ - self, AdtKind, CanonicalUserType, Ty, TyCtxt, GenericParamDefKind, Visibility, + self, AdtKind, CanonicalUserType, Ty, TyCtxt, Const, GenericParamDefKind, Visibility, ToPolyTraitRef, ToPredicate, RegionKind, UserType }; use rustc::ty::adjustment::{ @@ -1959,6 +1960,22 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { span: Span) -> Ty<'tcx> { if let UnpackedKind::Type(ty) = self.var_for_def(span, ty_param_def).unpack() { return ty; + fn ct_infer( + &self, + ty: Ty<'tcx>, + param: Option<&ty::GenericParamDef>, + span: Span, + ) -> &'tcx Const<'tcx> { + if let Some(param) = param { + if let UnpackedKind::Const(ct) = self.var_for_def(span, param).unpack() { + return ct; + } + unreachable!() + } else { + self.next_const_var(ty, ConstVariableOrigin { + kind: ConstVariableOriginKind::ConstInference, + span, + }) } unreachable!() } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 2751cd0a37ec0..64b92687cfe17 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -26,7 +26,7 @@ use rustc::ty::subst::{Subst, InternalSubsts}; use rustc::ty::util::Discr; use rustc::ty::util::IntTypeExt; use rustc::ty::subst::UnpackedKind; -use rustc::ty::{self, AdtKind, DefIdTree, ToPolyTraitRef, Ty, TyCtxt}; +use rustc::ty::{self, AdtKind, DefIdTree, ToPolyTraitRef, Ty, TyCtxt, Const}; use rustc::ty::{ReprOptions, ToPredicate}; use rustc::util::captures::Captures; use rustc::util::nodemap::FxHashMap; @@ -47,7 +47,7 @@ use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc::hir::GenericParamKind; use rustc::hir::{self, CodegenFnAttrFlags, CodegenFnAttrs, Unsafety}; -use errors::Applicability; +use errors::{Applicability, DiagnosticId}; use std::iter; @@ -204,6 +204,22 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { self.tcx().types.err } + fn ct_infer( + &self, + _: Ty<'tcx>, + _: Option<&ty::GenericParamDef>, + span: Span, + ) -> &'tcx Const<'tcx> { + self.tcx().sess.struct_span_err_with_code( + span, + "the const placeholder `_` is not allowed within types on item signatures", + DiagnosticId::Error("E0121".into()), + ).span_label(span, "not allowed in type signatures") + .emit(); + + self.tcx().consts.err + } + fn projected_ty_from_poly_trait_ref( &self, span: Span, diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index b5a50f4387581..66e9a6e6b2a2e 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -1482,8 +1482,8 @@ impl <'a> Drop for MyWrapper<'a> { "##, E0121: r##" -In order to be consistent with Rust's lack of global type inference, type -placeholders are disallowed by design in item signatures. +In order to be consistent with Rust's lack of global type inference, +type and const placeholders are disallowed by design in item signatures. Examples of this error include: From a0e3e9ab9d50c74e51a81d566c941dfee6733ce5 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 6 Jun 2019 01:55:34 +0100 Subject: [PATCH 05/10] Refactor `ty_infer` and `re_infer` --- src/librustc_typeck/astconv.rs | 31 +++++++++++++-------------- src/librustc_typeck/check/closure.rs | 2 +- src/librustc_typeck/check/mod.rs | 32 ++++++++++++++++------------ src/librustc_typeck/collect.rs | 13 ++++++----- 4 files changed, 40 insertions(+), 38 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 349c4e608c244..63d9f0920cc7b 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -49,19 +49,17 @@ pub trait AstConv<'gcx, 'tcx> { -> &'tcx ty::GenericPredicates<'tcx>; /// Returns the lifetime to use when a lifetime is omitted (and not elided). - fn re_infer(&self, span: Span, _def: Option<&ty::GenericParamDef>) + fn re_infer( + &self, + param: Option<&ty::GenericParamDef>, + span: Span, + ) -> Option>; /// Returns the type to use when a type is omitted. - fn ty_infer(&self, span: Span) -> Ty<'tcx>; + fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>; - /// Same as `ty_infer`, but with a known type parameter definition. - fn ty_infer_for_def(&self, - _def: &ty::GenericParamDef, - span: Span) -> Ty<'tcx> { - self.ty_infer(span) - } - /// What const should we use when a const is omitted? + /// Returns the const to use when a const is omitted. fn ct_infer( &self, ty: Ty<'tcx>, @@ -163,7 +161,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } None => { - self.re_infer(lifetime.span, def) + self.re_infer(def, lifetime.span) .unwrap_or_else(|| { // This indicates an illegal lifetime // elision. `resolve_lifetime` should have @@ -701,11 +699,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } } else if infer_args { // No type parameters were provided, we can infer all. - if !default_needs_object_self(param) { - self.ty_infer_for_def(param, span).into() + let param = if !default_needs_object_self(param) { + Some(param) } else { - self.ty_infer(span).into() - } + None + }; + self.ty_infer(param, span).into() } else { // We've already errored above about the mismatch. tcx.types.err.into() @@ -1440,7 +1439,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { if tcx.named_region(lifetime.hir_id).is_some() { self.ast_region_to_region(lifetime, None) } else { - self.re_infer(span, None).unwrap_or_else(|| { + self.re_infer(None, span).unwrap_or_else(|| { span_err!(tcx.sess, span, E0228, "the lifetime bound for this object type cannot be deduced \ from context; please supply an explicit bound"); @@ -2134,7 +2133,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { // values in a ExprKind::Closure, or as // the type of local variables. Both of these cases are // handled specially and will not descend into this routine. - self.ty_infer(ast_ty.span) + self.ty_infer(None, ast_ty.span) } hir::TyKind::CVarArgs(lt) => { let va_list_did = match tcx.lang_items().va_list() { diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 4427a83562e9e..b894fc8c83c10 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -598,7 +598,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let supplied_arguments = decl.inputs.iter().map(|a| astconv.ast_ty_to_ty(a)); let supplied_return = match decl.output { hir::Return(ref output) => astconv.ast_ty_to_ty(&output), - hir::DefaultReturn(_) => astconv.ty_infer(decl.output.span()), + hir::DefaultReturn(_) => astconv.ty_infer(None, decl.output.span()), }; let result = ty::Binder::bind(self.tcx.mk_fn_sig( diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index acb0b73af886d..0b558a20ed47e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1939,8 +1939,11 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { }) } - fn re_infer(&self, span: Span, def: Option<&ty::GenericParamDef>) - -> Option> { + fn re_infer( + &self, + def: Option<&ty::GenericParamDef>, + span: Span, + ) -> Option> { let v = match def { Some(def) => infer::EarlyBoundRegion(span, def.name), None => infer::MiscVariable(span) @@ -1948,18 +1951,20 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { Some(self.next_region_var(v)) } - fn ty_infer(&self, span: Span) -> Ty<'tcx> { - self.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, - span, - }) + fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> { + if let Some(param) = param { + if let UnpackedKind::Type(ty) = self.var_for_def(span, param).unpack() { + return ty; + } + unreachable!() + } else { + self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span, + }) + } } - fn ty_infer_for_def(&self, - ty_param_def: &ty::GenericParamDef, - span: Span) -> Ty<'tcx> { - if let UnpackedKind::Type(ty) = self.var_for_def(span, ty_param_def).unpack() { - return ty; fn ct_infer( &self, ty: Ty<'tcx>, @@ -1977,7 +1982,6 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { span, }) } - unreachable!() } fn projected_ty_from_poly_trait_ref(&self, @@ -5463,7 +5467,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { |substs, param, infer_args| { match param.kind { GenericParamDefKind::Lifetime => { - self.re_infer(span, Some(param)).unwrap().into() + self.re_infer(Some(param), span).unwrap().into() } GenericParamDefKind::Type { has_default, .. } => { if !infer_args && has_default { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 64b92687cfe17..8b770096cad09 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -186,18 +186,17 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { fn re_infer( &self, - _span: Span, - _def: Option<&ty::GenericParamDef>, + _: Option<&ty::GenericParamDef>, + _: Span, ) -> Option> { None } - fn ty_infer(&self, span: Span) -> Ty<'tcx> { - struct_span_err!( - self.tcx().sess, + fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> { + self.tcx().sess.struct_span_err_with_code( span, - E0121, - "the type placeholder `_` is not allowed within types on item signatures" + "the type placeholder `_` is not allowed within types on item signatures", + DiagnosticId::Error("E0121".into()), ).span_label(span, "not allowed in type signatures") .emit(); From 647b4a4deb8de06cdc375187ecaf29ebeaa65f98 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 6 Jun 2019 01:55:57 +0100 Subject: [PATCH 06/10] Add test for const generics struct constructor --- .../const-generics/array-wrapper-struct-ctor.rs | 15 +++++++++++++++ .../array-wrapper-struct-ctor.stderr | 6 ++++++ 2 files changed, 21 insertions(+) create mode 100644 src/test/ui/const-generics/array-wrapper-struct-ctor.rs create mode 100644 src/test/ui/const-generics/array-wrapper-struct-ctor.stderr diff --git a/src/test/ui/const-generics/array-wrapper-struct-ctor.rs b/src/test/ui/const-generics/array-wrapper-struct-ctor.rs new file mode 100644 index 0000000000000..d83846fcf88d4 --- /dev/null +++ b/src/test/ui/const-generics/array-wrapper-struct-ctor.rs @@ -0,0 +1,15 @@ +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +struct ArrayStruct { + data: [T; N], +} + +struct ArrayTuple([T; N]); + +fn main() { + let _ = ArrayStruct { data: [0u32; 8] }; + let _ = ArrayTuple([0u32; 8]); +} diff --git a/src/test/ui/const-generics/array-wrapper-struct-ctor.stderr b/src/test/ui/const-generics/array-wrapper-struct-ctor.stderr new file mode 100644 index 0000000000000..bd18264c1637d --- /dev/null +++ b/src/test/ui/const-generics/array-wrapper-struct-ctor.stderr @@ -0,0 +1,6 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/array-wrapper-struct-ctor.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + From 7bb0a16ad701c1cd22c0b2c05afd55f06a532062 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 6 Jun 2019 01:56:09 +0100 Subject: [PATCH 07/10] Add test for deriving Debug for const generics --- .../derive-debug-array-wrapper.rs | 9 +++++++++ .../derive-debug-array-wrapper.stderr | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/test/ui/const-generics/derive-debug-array-wrapper.rs create mode 100644 src/test/ui/const-generics/derive-debug-array-wrapper.stderr diff --git a/src/test/ui/const-generics/derive-debug-array-wrapper.rs b/src/test/ui/const-generics/derive-debug-array-wrapper.rs new file mode 100644 index 0000000000000..a29cb90ebb79a --- /dev/null +++ b/src/test/ui/const-generics/derive-debug-array-wrapper.rs @@ -0,0 +1,9 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +#[derive(Debug)] +struct X { + a: [u32; N], //~ ERROR `[u32; _]` doesn't implement `std::fmt::Debug` +} + +fn main() {} diff --git a/src/test/ui/const-generics/derive-debug-array-wrapper.stderr b/src/test/ui/const-generics/derive-debug-array-wrapper.stderr new file mode 100644 index 0000000000000..5bab1d1b54a3e --- /dev/null +++ b/src/test/ui/const-generics/derive-debug-array-wrapper.stderr @@ -0,0 +1,19 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/derive-debug-array-wrapper.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + +error[E0277]: `[u32; _]` doesn't implement `std::fmt::Debug` + --> $DIR/derive-debug-array-wrapper.rs:6:5 + | +LL | a: [u32; N], + | ^^^^^^^^^^^ `[u32; _]` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug` + | + = help: the trait `std::fmt::Debug` is not implemented for `[u32; _]` + = note: required because of the requirements on the impl of `std::fmt::Debug` for `&[u32; _]` + = note: required for the cast to the object type `dyn std::fmt::Debug` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From f11e6f7fa7d0a8ff1e73ff28b26667ee0a1acd87 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 7 Jun 2019 00:21:16 +0100 Subject: [PATCH 08/10] Fix issue with path segment lowering with const args --- src/librustc/hir/lowering.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 1b433c8da60b0..81ea96c0eb732 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2230,9 +2230,9 @@ impl<'a> LoweringContext<'a> { .collect(); if expected_lifetimes > 0 && param_mode == ParamMode::Explicit { let anon_lt_suggestion = vec!["'_"; expected_lifetimes].join(", "); - let no_ty_args = generic_args.args.len() == expected_lifetimes; + let no_non_lt_args = generic_args.args.len() == expected_lifetimes; let no_bindings = generic_args.bindings.is_empty(); - let (incl_angl_brckt, insertion_span, suggestion) = if no_ty_args && no_bindings { + let (incl_angl_brckt, insertion_sp, suggestion) = if no_non_lt_args && no_bindings { // If there are no (non-implicit) generic args or associated type // bindings, our suggestion includes the angle brackets. (true, path_span.shrink_to_hi(), format!("<{}>", anon_lt_suggestion)) @@ -2240,7 +2240,7 @@ impl<'a> LoweringContext<'a> { // Otherwise (sorry, this is kind of gross) we need to infer the // place to splice in the `'_, ` from the generics that do exist. let first_generic_span = first_generic_span - .expect("already checked that type args or bindings exist"); + .expect("already checked that non-lifetime args or bindings exist"); (false, first_generic_span.shrink_to_lo(), format!("{}, ", anon_lt_suggestion)) }; match self.anonymous_lifetime_mode { @@ -2263,7 +2263,7 @@ impl<'a> LoweringContext<'a> { expected_lifetimes, path_span, incl_angl_brckt, - insertion_span, + insertion_sp, suggestion, ); err.emit(); @@ -2280,7 +2280,7 @@ impl<'a> LoweringContext<'a> { expected_lifetimes, path_span, incl_angl_brckt, - insertion_span, + insertion_sp, suggestion, ) ); @@ -2316,9 +2316,10 @@ impl<'a> LoweringContext<'a> { mut itctx: ImplTraitContext<'_>, ) -> (hir::GenericArgs, bool) { let &AngleBracketedArgs { ref args, ref constraints, .. } = data; - let has_types = args.iter().any(|arg| match arg { + let has_non_lt_args = args.iter().any(|arg| match arg { + ast::GenericArg::Lifetime(_) => false, ast::GenericArg::Type(_) => true, - _ => false, + ast::GenericArg::Const(_) => true, }); ( hir::GenericArgs { @@ -2328,7 +2329,7 @@ impl<'a> LoweringContext<'a> { .collect(), parenthesized: false, }, - !has_types && param_mode == ParamMode::Optional + !has_non_lt_args && param_mode == ParamMode::Optional ) } From 1d045149f024f738c9175316a3660f6358ec86bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 9 Jun 2019 21:37:26 +0200 Subject: [PATCH 09/10] submodules: update clippy from 71be6f62 to c0dbd34b Changes: ```` travis: disable rls integration test. rustup https://github.com/rust-lang/rust/pull/61669/ Add OUTER_EXPN_INFO lint ```` --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy b/src/tools/clippy index 71be6f62fa920..c0dbd34ba99a9 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 71be6f62fa920c0bd10cdf3a29aeb8c6719a8075 +Subproject commit c0dbd34ba99a949ece25c297a4a377685eb89c7c From 56a7f1e77ecb264e1588924588071d2eef6e1840 Mon Sep 17 00:00:00 2001 From: Niels Sascha Reedijk Date: Sun, 27 Jan 2019 09:25:25 +0100 Subject: [PATCH 10/10] Haiku: the maximum stack size is 16 MB When one tries to create a thread with a requested stack size larger than 16 MB, the call will fail and the compiler will bail out. Therefore we should limit the size of the thread stack to 16 MB on Haiku. --- src/librustc_interface/util.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index f4f7456a97ad6..a86d3cc43948d 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -121,9 +121,13 @@ pub fn create_session( } // Temporarily have stack size set to 32MB to deal with various crates with long method -// chains or deep syntax trees. +// chains or deep syntax trees, except when on Haiku. // FIXME(oli-obk): get https://github.com/rust-lang/rust/pull/55617 the finish line -const STACK_SIZE: usize = 32 * 1024 * 1024; // 32MB +#[cfg(not(target_os = "haiku"))] +const STACK_SIZE: usize = 32 * 1024 * 1024; + +#[cfg(target_os = "haiku")] +const STACK_SIZE: usize = 16 * 1024 * 1024; fn get_stack_size() -> Option { // FIXME: Hacks on hacks. If the env is trying to override the stack size