diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index b609af16ffe5b..8d9a51742fd97 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1326,30 +1326,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. @@ -1437,7 +1417,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 @@ -1494,7 +1477,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 @@ -1572,7 +1558,10 @@ 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) } // Simple bootstrap implementations of minnum/maxnum for stage0 compilation. diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e7f52b48cb9ed..b5e9f6bd3a610 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) => { @@ -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, ) ); @@ -2305,7 +2305,7 @@ impl<'a> LoweringContext<'a> { Some(id), Some(self.lower_res(res)), generic_args, - infer_types, + infer_args, ) } @@ -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 ) } diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 3edd75fb725da..6a561f0c63a2a 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -582,9 +582,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/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 27ee664aa5f58..1b4c56c3453a1 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_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 diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 34f817ba570e7..63d9f0920cc7b 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; @@ -49,18 +49,23 @@ 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) - } + /// Returns the const to 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 @@ -156,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 @@ -191,7 +196,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 +213,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 +264,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 +277,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 @@ -280,7 +285,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 +337,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 +408,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, @@ -414,7 +418,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 +515,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 +539,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 +560,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 +596,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 +621,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 +648,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 +665,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,13 +697,14 @@ 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() + 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() @@ -707,8 +712,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() + } } } }, @@ -880,7 +891,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)) }) } @@ -1428,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"); @@ -2122,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 a111851aa3797..0b558a20ed47e 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::{ @@ -1938,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) @@ -1947,20 +1951,37 @@ 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>, + 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!() } fn projected_ty_from_poly_trait_ref(&self, @@ -5419,10 +5440,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 +5464,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() + self.re_infer(Some(param), span).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. diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index f738f90b31eb6..5d91794506c6a 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; @@ -186,24 +186,39 @@ 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(); 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: diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 36a1628014ddb..95095c712d2c5 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> { 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)] + | ^^^^^^^^^^^^^^ + 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`. 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