From: bors Date: Tue, 11 Jun 2019 05:24:41 +0000 (+0000) Subject: Auto merge of #61492 - RalfJung:const-qualif-comments, r=eddyb X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=9d9c7ad323f95612d933106d65e3057ca9a0434f;hp=0edf46f7d1db0f09dc07bf93ed466ea067d50054;p=rust.git Auto merge of #61492 - RalfJung:const-qualif-comments, r=eddyb Const qualification comments I extracted some const-qualif knowledge from @eddyb. This is my attempt to turn that into comments. Cc @oli-obk @eddyb --- diff --git a/Cargo.lock b/Cargo.lock index 7f35b7344df..948074ce0fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2263,7 +2263,7 @@ dependencies = [ [[package]] name = "rls" -version = "1.36.0" +version = "1.37.0" dependencies = [ "cargo 0.38.0", "cargo_metadata 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index b609af16ffe..8d9a51742fd 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1326,30 +1326,10 @@ pub fn volatile_copy_nonoverlapping_memory(dst: *mut T, src: *const T, 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 e7f52b48cb9..b5e9f6bd3a6 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2168,7 +2168,7 @@ fn lower_path_segment( 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 @@ fn lower_path_segment( .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 @@ fn lower_path_segment( // 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 @@ fn lower_path_segment( expected_lifetimes, path_span, incl_angl_brckt, - insertion_span, + insertion_sp, suggestion, ); err.emit(); @@ -2280,7 +2280,7 @@ fn lower_path_segment( expected_lifetimes, path_span, incl_angl_brckt, - insertion_span, + insertion_sp, suggestion, ) ); @@ -2305,7 +2305,7 @@ fn lower_path_segment( Some(id), Some(self.lower_res(res)), generic_args, - infer_types, + infer_args, ) } @@ -2316,9 +2316,10 @@ fn lower_angle_bracketed_parameter_data( 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 @@ fn lower_angle_bracketed_parameter_data( .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 3edd75fb725..6a561f0c63a 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -582,9 +582,17 @@ pub fn to_string(&self) -> String { } } +/// 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 27ee664aa5f..1b4c56c3453 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 @@ pub fn from_ident(ident: Ident) -> PathSegment { ident, hir_id: None, res: None, - infer_types: true, + infer_args: true, args: None, } } @@ -368,13 +368,13 @@ pub fn new( 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 c8615f0ed1b..7b0a499fa5c 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1196,7 +1196,7 @@ fn print_expr_method_call(&mut self, 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 @@ pub fn print_path(&mut self, 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 @@ pub fn print_path_segment(&mut self, segment: &hir::PathSegment) -> io::Result<( 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 @@ pub fn print_qpath(&mut self, 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 @@ pub fn print_qpath(&mut self, 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 @@ pub fn print_qpath(&mut self, 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 @@ pub fn print_qpath(&mut self, 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 @@ fn print_generic_args(&mut self, // 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 f4f7456a97a..a86d3cc4394 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_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index a695a90f2ae..cda6b60b767 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -1016,7 +1016,7 @@ pub fn new(odir: Option<&'a Path>, cratename: &str) -> DumpHandler<'a> { } } - fn output_file(&self, ctx: &SaveContext<'_, '_>) -> File { + fn output_file(&self, ctx: &SaveContext<'_, '_>) -> (File, PathBuf) { let sess = &ctx.tcx.sess; let file_name = match ctx.config.output_file { Some(ref s) => PathBuf::from(s), @@ -1054,7 +1054,7 @@ fn output_file(&self, ctx: &SaveContext<'_, '_>) -> File { |e| sess.fatal(&format!("Could not open {}: {}", file_name.display(), e)), ); - output_file + (output_file, file_name) } } @@ -1066,13 +1066,23 @@ fn save<'l, 'tcx>( cratename: &str, input: &'l Input, ) { - let output = &mut self.output_file(&save_ctxt); - let mut dumper = JsonDumper::new(output, save_ctxt.config.clone()); - let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper); + let sess = &save_ctxt.tcx.sess; + let file_name = { + let (mut output, file_name) = self.output_file(&save_ctxt); + let mut dumper = JsonDumper::new(&mut output, save_ctxt.config.clone()); + let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper); - visitor.dump_crate_info(cratename, krate); - visitor.dump_compilation_options(input, cratename); - visit::walk_crate(&mut visitor, krate); + visitor.dump_crate_info(cratename, krate); + visitor.dump_compilation_options(input, cratename); + visit::walk_crate(&mut visitor, krate); + + file_name + }; + + if sess.opts.debugging_opts.emit_artifact_notifications { + sess.parse_sess.span_diagnostic + .emit_artifact_notification(&file_name, "save-analysis"); + } } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 34f817ba570..63d9f0920cc 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -13,7 +13,7 @@ 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 @@ fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> &'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 @@ pub fn ast_region_to_region(&self, } 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 @@ pub fn ast_path_substs_for_ty(&self, span, def_id, generic_args, - item_segment.infer_types, + item_segment.infer_args, None, ) }); @@ -208,7 +213,7 @@ fn check_impl_trait( 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 @@ pub fn check_generic_arg_count_for_call( 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 @@ fn check_generic_arg_count( 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 @@ fn check_generic_arg_count( 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 @@ fn check_generic_arg_count( 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 @@ fn check_generic_arg_count( ); } // 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 @@ fn check_generic_arg_count( ); } // 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 @@ pub fn create_substs_for_generic_args<'a, 'b>( } // 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 @@ pub fn create_substs_for_generic_args<'a, 'b>( | (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 @@ pub fn create_substs_for_generic_args<'a, 'b>( (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 @@ fn create_substs_for_ast_path<'a>(&self, 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 @@ fn create_substs_for_ast_path<'a>(&self, &generic_args, GenericArgPosition::Type, has_self, - infer_types, + infer_args, ); let is_object = self_ty.map_or(false, |ty| { @@ -644,7 +648,7 @@ fn create_substs_for_ast_path<'a>(&self, 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 @@ fn create_substs_for_ast_path<'a>(&self, } }, // 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 @@ fn create_substs_for_ast_path<'a>(&self, .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 @@ fn create_substs_for_ast_path<'a>(&self, } 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 @@ fn create_substs_for_ast_trait_ref( 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 @@ fn conv_object_ty_poly_trait_ref(&self, 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 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> { // 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 4427a83562e..b894fc8c83c 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -598,7 +598,7 @@ fn supplied_sig_of_closure( 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 a111851aa37..0b558a20ed4 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -100,11 +100,12 @@ 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 @@ fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) }) } - 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 @@ fn re_infer(&self, span: Span, def: Option<&ty::GenericParamDef>) 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 @@ pub fn instantiate_value_path(&self, 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 @@ pub fn instantiate_value_path(&self, } }, // 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 f738f90b31e..5d91794506c 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -26,7 +26,7 @@ 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::GenericParamKind; use rustc::hir::{self, CodegenFnAttrFlags, CodegenFnAttrs, Unsafety}; -use errors::Applicability; +use errors::{Applicability, DiagnosticId}; use std::iter; @@ -186,24 +186,39 @@ fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) 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 b5a50f43875..66e9a6e6b2a 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -1482,8 +1482,8 @@ fn drop(&mut self) {} "##, 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 36a1628014d..95095c712d2 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/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 2f4c48d4bf9..9df2898696e 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -130,7 +130,7 @@ fn is_eof(&self) -> bool { self.ch.is_none() } - fn fail_unterminated_raw_string(&self, pos: BytePos, hash_count: u16) { + fn fail_unterminated_raw_string(&self, pos: BytePos, hash_count: u16) -> ! { let mut err = self.struct_span_fatal(pos, pos, "unterminated raw string"); err.span_label(self.mk_sp(pos, pos), "unterminated raw string"); @@ -292,15 +292,6 @@ fn struct_fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: self.sess.span_diagnostic.struct_span_fatal(self.mk_sp(from_pos, to_pos), &m[..]) } - /// Report a lexical error spanning [`from_pos`, `to_pos`), appending an - /// escaped character to the error message - fn err_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) { - let mut m = m.to_string(); - m.push_str(": "); - push_escaped_char(&mut m, c); - self.err_span_(from_pos, to_pos, &m[..]); - } - /// Advance peek_token to refer to the next token, and /// possibly update the interner. fn advance_token(&mut self) -> Result<(), ()> { @@ -1070,7 +1061,13 @@ fn next_token_inner(&mut self) -> Result { self.validate_byte_str_escape(start_with_quote); (token::ByteStr, symbol) }, - Some('r') => self.scan_raw_byte_string(), + Some('r') => { + let (start, end, hash_count) = self.scan_raw_string(); + let symbol = self.name_from_to(start, end); + self.validate_raw_byte_str_escape(start, end); + + (token::ByteStrRaw(hash_count), symbol) + } _ => unreachable!(), // Should have been a token::Ident above. }; let suffix = self.scan_optional_raw_name(); @@ -1086,79 +1083,9 @@ fn next_token_inner(&mut self) -> Result { Ok(TokenKind::lit(token::Str, symbol, suffix)) } 'r' => { - let start_bpos = self.pos; - self.bump(); - let mut hash_count: u16 = 0; - while self.ch_is('#') { - if hash_count == 65535 { - let bpos = self.next_pos; - self.fatal_span_(start_bpos, - bpos, - "too many `#` symbols: raw strings may be \ - delimited by up to 65535 `#` symbols").raise(); - } - self.bump(); - hash_count += 1; - } - - if self.is_eof() { - self.fail_unterminated_raw_string(start_bpos, hash_count); - } else if !self.ch_is('"') { - let last_bpos = self.pos; - let curr_char = self.ch.unwrap(); - self.fatal_span_char(start_bpos, - last_bpos, - "found invalid character; only `#` is allowed \ - in raw string delimitation", - curr_char).raise(); - } - self.bump(); - let content_start_bpos = self.pos; - let mut content_end_bpos; - let mut valid = true; - 'outer: loop { - if self.is_eof() { - self.fail_unterminated_raw_string(start_bpos, hash_count); - } - // if self.ch_is('"') { - // content_end_bpos = self.pos; - // for _ in 0..hash_count { - // self.bump(); - // if !self.ch_is('#') { - // continue 'outer; - let c = self.ch.unwrap(); - match c { - '"' => { - content_end_bpos = self.pos; - for _ in 0..hash_count { - self.bump(); - if !self.ch_is('#') { - continue 'outer; - } - } - break; - } - '\r' => { - if !self.nextch_is('\n') { - let last_bpos = self.pos; - self.err_span_(start_bpos, - last_bpos, - "bare CR not allowed in raw string, use \\r \ - instead"); - valid = false; - } - } - _ => (), - } - self.bump(); - } - - self.bump(); - let symbol = if valid { - self.name_from_to(content_start_bpos, content_end_bpos) - } else { - Symbol::intern("??") - }; + let (start, end, hash_count) = self.scan_raw_string(); + let symbol = self.name_from_to(start, end); + self.validate_raw_str_escape(start, end); let suffix = self.scan_optional_raw_name(); Ok(TokenKind::lit(token::StrRaw(hash_count), symbol, suffix)) @@ -1315,16 +1242,18 @@ fn scan_double_quoted_string(&mut self, unterminated_msg: &str) -> ast::Name { id } - fn scan_raw_byte_string(&mut self) -> (token::LitKind, Symbol) { + /// Scans a raw (byte) string, returning byte position range for `""` + /// (including quotes) along with `#` character count in `(b)r##...""##...`; + fn scan_raw_string(&mut self) -> (BytePos, BytePos, u16) { let start_bpos = self.pos; self.bump(); - let mut hash_count = 0; + let mut hash_count: u16 = 0; while self.ch_is('#') { if hash_count == 65535 { let bpos = self.next_pos; self.fatal_span_(start_bpos, bpos, - "too many `#` symbols: raw byte strings may be \ + "too many `#` symbols: raw strings may be \ delimited by up to 65535 `#` symbols").raise(); } self.bump(); @@ -1334,13 +1263,13 @@ fn scan_raw_byte_string(&mut self) -> (token::LitKind, Symbol) { if self.is_eof() { self.fail_unterminated_raw_string(start_bpos, hash_count); } else if !self.ch_is('"') { - let pos = self.pos; - let ch = self.ch.unwrap(); + let last_bpos = self.pos; + let curr_char = self.ch.unwrap(); self.fatal_span_char(start_bpos, - pos, - "found invalid character; only `#` is allowed in raw \ - string delimitation", - ch).raise(); + last_bpos, + "found invalid character; only `#` is allowed \ + in raw string delimitation", + curr_char).raise(); } self.bump(); let content_start_bpos = self.pos; @@ -1360,19 +1289,14 @@ fn scan_raw_byte_string(&mut self) -> (token::LitKind, Symbol) { } break; } - Some(c) => { - if c > '\x7F' { - let pos = self.pos; - self.err_span_char(pos, pos, "raw byte string must be ASCII", c); - } - } + _ => (), } self.bump(); } self.bump(); - (token::ByteStrRaw(hash_count), self.name_from_to(content_start_bpos, content_end_bpos)) + (content_start_bpos, content_end_bpos, hash_count) } fn validate_char_escape(&self, start_with_quote: BytePos) { @@ -1422,6 +1346,40 @@ fn validate_str_escape(&self, start_with_quote: BytePos) { }); } + fn validate_raw_str_escape(&self, content_start: BytePos, content_end: BytePos) { + self.with_str_from_to(content_start, content_end, |lit: &str| { + unescape::unescape_raw_str(lit, &mut |range, c| { + if let Err(err) = c { + emit_unescape_error( + &self.sess.span_diagnostic, + lit, + self.mk_sp(content_start - BytePos(1), content_end + BytePos(1)), + unescape::Mode::Str, + range, + err, + ) + } + }) + }); + } + + fn validate_raw_byte_str_escape(&self, content_start: BytePos, content_end: BytePos) { + self.with_str_from_to(content_start, content_end, |lit: &str| { + unescape::unescape_raw_byte_str(lit, &mut |range, c| { + if let Err(err) = c { + emit_unescape_error( + &self.sess.span_diagnostic, + lit, + self.mk_sp(content_start - BytePos(1), content_end + BytePos(1)), + unescape::Mode::ByteStr, + range, + err, + ) + } + }) + }); + } + fn validate_byte_str_escape(&self, start_with_quote: BytePos) { self.with_str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1), |lit| { unescape::unescape_byte_str(lit, &mut |range, c| { diff --git a/src/libsyntax/parse/literal.rs b/src/libsyntax/parse/literal.rs index 84f7386235f..ef55bf6b929 100644 --- a/src/libsyntax/parse/literal.rs +++ b/src/libsyntax/parse/literal.rs @@ -4,7 +4,9 @@ use crate::parse::parser::Parser; use crate::parse::PResult; use crate::parse::token::{self, Token, TokenKind}; -use crate::parse::unescape::{unescape_str, unescape_char, unescape_byte_str, unescape_byte}; +use crate::parse::unescape::{unescape_char, unescape_byte}; +use crate::parse::unescape::{unescape_str, unescape_byte_str}; +use crate::parse::unescape::{unescape_raw_str, unescape_raw_byte_str}; use crate::print::pprust; use crate::symbol::{kw, sym, Symbol}; use crate::tokenstream::{TokenStream, TokenTree}; @@ -141,7 +143,17 @@ fn from_lit_token(lit: token::Lit) -> Result { // Ditto. let s = symbol.as_str(); let symbol = if s.contains('\r') { - Symbol::intern(&raw_str_lit(&s)) + let mut buf = String::with_capacity(s.len()); + let mut error = Ok(()); + unescape_raw_str(&s, &mut |_, unescaped_char| { + match unescaped_char { + Ok(c) => buf.push(c), + Err(_) => error = Err(LitError::LexerError), + } + }); + error?; + buf.shrink_to_fit(); + Symbol::intern(&buf) } else { symbol }; @@ -161,7 +173,26 @@ fn from_lit_token(lit: token::Lit) -> Result { buf.shrink_to_fit(); LitKind::ByteStr(Lrc::new(buf)) } - token::ByteStrRaw(_) => LitKind::ByteStr(Lrc::new(symbol.to_string().into_bytes())), + token::ByteStrRaw(_) => { + let s = symbol.as_str(); + let bytes = if s.contains('\r') { + let mut buf = Vec::with_capacity(s.len()); + let mut error = Ok(()); + unescape_raw_byte_str(&s, &mut |_, unescaped_byte| { + match unescaped_byte { + Ok(c) => buf.push(c), + Err(_) => error = Err(LitError::LexerError), + } + }); + error?; + buf.shrink_to_fit(); + buf + } else { + symbol.to_string().into_bytes() + }; + + LitKind::ByteStr(Lrc::new(bytes)) + }, token::Err => LitKind::Err(symbol), }) } @@ -353,29 +384,6 @@ impl<'a> Parser<'a> { } } -/// Parses a string representing a raw string literal into its final form. The -/// only operation this does is convert embedded CRLF into a single LF. -fn raw_str_lit(lit: &str) -> String { - debug!("raw_str_lit: {:?}", lit); - let mut res = String::with_capacity(lit.len()); - - let mut chars = lit.chars().peekable(); - while let Some(c) = chars.next() { - if c == '\r' { - if *chars.peek().unwrap() != '\n' { - panic!("lexer accepted bare CR"); - } - chars.next(); - res.push('\n'); - } else { - res.push(c); - } - } - - res.shrink_to_fit(); - res -} - // Checks if `s` looks like i32 or u1234 etc. fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit()) diff --git a/src/libsyntax/parse/unescape.rs b/src/libsyntax/parse/unescape.rs index 90ee549db01..22cce67b5ee 100644 --- a/src/libsyntax/parse/unescape.rs +++ b/src/libsyntax/parse/unescape.rs @@ -1,4 +1,4 @@ -//! Utilities for validating string and char literals and turning them into +//! Utilities for validating string and char literals and turning them into //! values they represent. use std::str::Chars; @@ -12,6 +12,7 @@ pub(crate) enum EscapeError { LoneSlash, InvalidEscape, BareCarriageReturn, + BareCarriageReturnInRawString, EscapeOnlyChar, TooShortHexEscape, @@ -29,6 +30,7 @@ pub(crate) enum EscapeError { UnicodeEscapeInByte, NonAsciiCharInByte, + NonAsciiCharInByteString, } /// Takes a contents of a char literal (without quotes), and returns an @@ -66,6 +68,30 @@ pub(crate) fn unescape_byte_str(literal_text: &str, callback: &mut F) }) } +/// Takes a contents of a string literal (without quotes) and produces a +/// sequence of characters or errors. +/// NOTE: Raw strings do not perform any explicit character escaping, here we +/// only translate CRLF to LF and produce errors on bare CR. +pub(crate) fn unescape_raw_str(literal_text: &str, callback: &mut F) +where + F: FnMut(Range, Result), +{ + unescape_raw_str_or_byte_str(literal_text, Mode::Str, callback) +} + +/// Takes a contents of a string literal (without quotes) and produces a +/// sequence of characters or errors. +/// NOTE: Raw strings do not perform any explicit character escaping, here we +/// only translate CRLF to LF and produce errors on bare CR. +pub(crate) fn unescape_raw_byte_str(literal_text: &str, callback: &mut F) +where + F: FnMut(Range, Result), +{ + unescape_raw_str_or_byte_str(literal_text, Mode::ByteStr, &mut |range, char| { + callback(range, char.map(byte_from_char)) + }) +} + #[derive(Debug, Clone, Copy)] pub(crate) enum Mode { Char, @@ -254,9 +280,40 @@ fn skip_ascii_whitespace(chars: &mut Chars<'_>) { } } +/// Takes a contents of a string literal (without quotes) and produces a +/// sequence of characters or errors. +/// NOTE: Raw strings do not perform any explicit character escaping, here we +/// only translate CRLF to LF and produce errors on bare CR. +fn unescape_raw_str_or_byte_str(literal_text: &str, mode: Mode, callback: &mut F) +where + F: FnMut(Range, Result), +{ + assert!(mode.in_double_quotes()); + let initial_len = literal_text.len(); + + let mut chars = literal_text.chars(); + while let Some(curr) = chars.next() { + let start = initial_len - chars.as_str().len() - curr.len_utf8(); + + let result = match (curr, chars.clone().next()) { + ('\r', Some('\n')) => { + chars.next(); + Ok('\n') + }, + ('\r', _) => Err(EscapeError::BareCarriageReturnInRawString), + (c, _) if mode.is_bytes() && !c.is_ascii() => + Err(EscapeError::NonAsciiCharInByteString), + (c, _) => Ok(c), + }; + let end = initial_len - chars.as_str().len(); + + callback(start..end, result); + } +} + fn byte_from_char(c: char) -> u8 { let res = c as u32; - assert!(res <= u8::max_value() as u32, "guaranteed because of Mode::Byte"); + assert!(res <= u8::max_value() as u32, "guaranteed because of Mode::Byte(Str)"); res as u8 } diff --git a/src/libsyntax/parse/unescape_error_reporting.rs b/src/libsyntax/parse/unescape_error_reporting.rs index 22777c0884f..71b41161ad8 100644 --- a/src/libsyntax/parse/unescape_error_reporting.rs +++ b/src/libsyntax/parse/unescape_error_reporting.rs @@ -80,6 +80,11 @@ pub(crate) fn emit_unescape_error( }; handler.span_err(span, msg); } + EscapeError::BareCarriageReturnInRawString => { + assert!(mode.in_double_quotes()); + let msg = "bare CR not allowed in raw string"; + handler.span_err(span, msg); + } EscapeError::InvalidEscape => { let (c, span) = last_char(); @@ -124,6 +129,11 @@ pub(crate) fn emit_unescape_error( handler.span_err(span, "byte constant must be ASCII. \ Use a \\xHH escape for a non-ASCII byte") } + EscapeError::NonAsciiCharInByteString => { + assert!(mode.is_bytes()); + let (_c, span) = last_char(); + handler.span_err(span, "raw byte string must be ASCII") + } EscapeError::OutOfRangeHexEscape => { handler.span_err(span, "this form of character escape may only be used \ with characters in the range [\\x00-\\x7f]") diff --git a/src/test/run-pass/lexer-crlf-line-endings-string-literal-doc-comment.rs b/src/test/run-pass/lexer-crlf-line-endings-string-literal-doc-comment.rs index 126cab67c1c..f9d1b17b8dd 100644 --- a/src/test/run-pass/lexer-crlf-line-endings-string-literal-doc-comment.rs +++ b/src/test/run-pass/lexer-crlf-line-endings-string-literal-doc-comment.rs @@ -30,6 +30,9 @@ fn main() { let s = r"string literal"; assert_eq!(s, "string\nliteral"); + let s = br"byte string +literal"; + assert_eq!(s, "byte string\nliteral".as_bytes()); // validate that our source file has CRLF endings let source = include_str!("lexer-crlf-line-endings-string-literal-doc-comment.rs"); 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 00000000000..d83846fcf88 --- /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 00000000000..bd18264c163 --- /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 00000000000..a29cb90ebb7 --- /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 00000000000..5bab1d1b54a --- /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/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr index 7d944569ca9..b0fe4b6acd4 100644 --- a/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr +++ b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr @@ -28,11 +28,11 @@ error: bare CR not allowed in string, use \r instead LL | let _s = "foo bar"; | ^ -error: bare CR not allowed in raw string, use \r instead - --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:24:14 +error: bare CR not allowed in raw string + --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:24:19 | LL | let _s = r"bar foo"; - | ^^^^^ + | ^ error: unknown character escape: \r --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:27:19 diff --git a/src/test/ui/parser/raw-byte-string-literals.rs b/src/test/ui/parser/raw-byte-string-literals.rs index 3b50fb8036a..534afabdf77 100644 --- a/src/test/ui/parser/raw-byte-string-literals.rs +++ b/src/test/ui/parser/raw-byte-string-literals.rs @@ -1,4 +1,7 @@ +// ignore-tidy-cr +// compile-flags: -Z continue-parse-after-error pub fn main() { + br"a "; //~ ERROR bare CR not allowed in raw string br"é"; //~ ERROR raw byte string must be ASCII br##~"a"~##; //~ ERROR only `#` is allowed in raw string delimitation } diff --git a/src/test/ui/parser/raw-byte-string-literals.stderr b/src/test/ui/parser/raw-byte-string-literals.stderr index 671ed97d1b5..4880d1fdbe8 100644 --- a/src/test/ui/parser/raw-byte-string-literals.stderr +++ b/src/test/ui/parser/raw-byte-string-literals.stderr @@ -1,14 +1,20 @@ -error: raw byte string must be ASCII: \u{e9} - --> $DIR/raw-byte-string-literals.rs:2:8 +error: bare CR not allowed in raw string + --> $DIR/raw-byte-string-literals.rs:4:9 + | +LL | br"a "; + | ^ + +error: raw byte string must be ASCII + --> $DIR/raw-byte-string-literals.rs:5:8 | LL | br"é"; | ^ error: found invalid character; only `#` is allowed in raw string delimitation: ~ - --> $DIR/raw-byte-string-literals.rs:3:6 + --> $DIR/raw-byte-string-literals.rs:6:6 | LL | br##~"a"~##; | ^^^ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/src/test/ui/save-analysis/emit-notifications.nll.stderr b/src/test/ui/save-analysis/emit-notifications.nll.stderr new file mode 100644 index 00000000000..60734cedb50 --- /dev/null +++ b/src/test/ui/save-analysis/emit-notifications.nll.stderr @@ -0,0 +1,2 @@ +{"artifact":"$TEST_BUILD_DIR/save-analysis/emit-notifications.nll/save-analysis/libemit_notifications.json","emit":"save-analysis"} +{"artifact":"$TEST_BUILD_DIR/save-analysis/emit-notifications.nll/libemit_notifications.rlib","emit":"link"} diff --git a/src/test/ui/save-analysis/emit-notifications.rs b/src/test/ui/save-analysis/emit-notifications.rs new file mode 100644 index 00000000000..411acbb14db --- /dev/null +++ b/src/test/ui/save-analysis/emit-notifications.rs @@ -0,0 +1,4 @@ +// compile-pass +// compile-flags: -Zsave-analysis -Zemit-artifact-notifications +// compile-flags: --crate-type rlib --error-format=json +pub fn foo() {} diff --git a/src/test/ui/save-analysis/emit-notifications.stderr b/src/test/ui/save-analysis/emit-notifications.stderr new file mode 100644 index 00000000000..e16f60f8b5f --- /dev/null +++ b/src/test/ui/save-analysis/emit-notifications.stderr @@ -0,0 +1,2 @@ +{"artifact":"$TEST_BUILD_DIR/save-analysis/emit-notifications/save-analysis/libemit_notifications.json","emit":"save-analysis"} +{"artifact":"$TEST_BUILD_DIR/save-analysis/emit-notifications/libemit_notifications.rlib","emit":"link"} diff --git a/src/tools/clippy b/src/tools/clippy index 71be6f62fa9..c0dbd34ba99 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 71be6f62fa920c0bd10cdf3a29aeb8c6719a8075 +Subproject commit c0dbd34ba99a949ece25c297a4a377685eb89c7c diff --git a/src/tools/rls b/src/tools/rls index d1e20280dc1..483dcbc73f9 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit d1e20280dc188f542c083a738f8da3fef25af478 +Subproject commit 483dcbc73f9923e98c71ec9df11ee3d0d5cfb467