[[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)",
pub fn nontemporal_store<T>(ptr: *mut T, val: T);
}
-mod real_intrinsics {
- extern "rust-intrinsic" {
- /// Copies `count * size_of::<T>()` 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<T>(src: *const T, dst: *mut T, count: usize);
-
- /// Copies `count * size_of::<T>()` 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<T>(src: *const T, dst: *mut T, count: usize);
-
- /// Sets `count * size_of::<T>()` 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<T>(dst: *mut T, val: u8, count: usize);
- }
-}
+// Some functions are defined here because they accidentally got made
+// available in this module on stable. See <https://github.com/rust-lang/rust/issues/15702>.
+// (`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::<T>()` bytes from `src` to `dst`. The source
/// and destination must *not* overlap.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
- real_intrinsics::copy_nonoverlapping(src, dst, count);
+ extern "rust-intrinsic" {
+ fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+ }
+ copy_nonoverlapping(src, dst, count);
}
/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
- real_intrinsics::copy(src, dst, count)
+ extern "rust-intrinsic" {
+ fn copy<T>(src: *const T, dst: *mut T, count: usize);
+ }
+ copy(src, dst, count)
}
/// Sets `count * size_of::<T>()` bytes of memory starting at `dst` to
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
- real_intrinsics::write_bytes(dst, val, count)
+ extern "rust-intrinsic" {
+ fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
+ }
+ write_bytes(dst, val, count)
}
// Simple bootstrap implementations of minnum/maxnum for stage0 compilation.
itctx: ImplTraitContext<'_>,
explicit_owner: Option<NodeId>,
) -> 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) => {
.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))
// 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 {
expected_lifetimes,
path_span,
incl_angl_brckt,
- insertion_span,
+ insertion_sp,
suggestion,
);
err.emit();
expected_lifetimes,
path_span,
incl_angl_brckt,
- insertion_span,
+ insertion_sp,
suggestion,
)
);
Some(id),
Some(self.lower_res(res)),
generic_args,
- infer_types,
+ infer_args,
)
}
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 {
.collect(),
parenthesized: false,
},
- !has_types && param_mode == ParamMode::Optional
+ !has_non_lt_args && param_mode == ParamMode::Optional
)
}
}
}
+/// 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
/// 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 `<Vec<..>>::new::<..>`.
- pub infer_types: bool,
+ pub infer_args: bool,
}
impl PathSegment {
ident,
hir_id: None,
res: None,
- infer_types: true,
+ infer_args: true,
args: None,
}
}
hir_id: Option<HirId>,
res: Option<Res>,
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 {
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(())
})?;
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)
})?;
}
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(())
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)
})?;
}
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)
})
}
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)
})
}
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 {
// 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("..")?;
}
}
// 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<usize> {
// FIXME: Hacks on hacks. If the env is trying to override the stack size
}
}
- 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),
|e| sess.fatal(&format!("Could not open {}: {}", file_name.display(), e)),
);
- output_file
+ (output_file, file_name)
}
}
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");
+ }
}
}
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;
-> &'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<ty::Region<'tcx>>;
/// 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
}
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
span,
def_id,
generic_args,
- item_segment.infer_types,
+ item_segment.infer_args,
None,
)
});
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), ..
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
}
args: &hir::GenericArgs,
position: GenericArgPosition,
has_self: bool,
- infer_types: bool,
+ infer_args: bool,
) -> (bool, Option<Vec<Span>>) {
// 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
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 {
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);
);
}
// 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,
);
}
// 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",
}
// 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();
| (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();
}
(_, _) => {
(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();
}
span: Span,
def_id: DefId,
generic_args: &'a hir::GenericArgs,
- infer_types: bool,
+ infer_args: bool,
self_ty: Option<Ty<'tcx>>)
-> (SubstsRef<'tcx>, Vec<ConvertedBinding<'tcx>>, Option<Vec<Span>>)
{
&generic_args,
GenericArgPosition::Type,
has_self,
- infer_types,
+ infer_args,
);
let is_object = self_ty.map_or(false, |ty| {
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) {
}
},
// 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
.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()
}
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()
+ }
}
}
},
self.create_substs_for_ast_path(span,
trait_def_id,
generic_args,
- trait_segment.infer_types,
+ trait_segment.infer_args,
Some(self_ty))
})
}
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");
// 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() {
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(
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::{
})
}
- fn re_infer(&self, span: Span, def: Option<&ty::GenericParamDef>)
- -> Option<ty::Region<'tcx>> {
+ fn re_infer(
+ &self,
+ def: Option<&ty::GenericParamDef>,
+ span: Span,
+ ) -> Option<ty::Region<'tcx>> {
let v = match def {
Some(def) => infer::EarlyBoundRegion(span, def.name),
None => infer::MiscVariable(span)
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,
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)
}
},
// 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.
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;
use rustc::hir::GenericParamKind;
use rustc::hir::{self, CodegenFnAttrFlags, CodegenFnAttrs, Unsafety};
-use errors::Applicability;
+use errors::{Applicability, DiagnosticId};
use std::iter;
fn re_infer(
&self,
- _span: Span,
- _def: Option<&ty::GenericParamDef>,
+ _: Option<&ty::GenericParamDef>,
+ _: Span,
) -> Option<ty::Region<'tcx>> {
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,
"##,
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:
($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 {
impl<$($name:Decodable),*> Decodable for ($($name,)*) {
#[allow(non_snake_case)]
fn decode<D: Decoder>(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> {
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");
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<(), ()> {
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();
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))
id
}
- fn scan_raw_byte_string(&mut self) -> (token::LitKind, Symbol) {
+ /// Scans a raw (byte) string, returning byte position range for `"<literal>"`
+ /// (including quotes) along with `#` character count in `(b)r##..."<literal>"##...`;
+ 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();
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;
}
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) {
});
}
+ 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| {
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};
// 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
};
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),
})
}
}
}
-/// 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())
-//! 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;
LoneSlash,
InvalidEscape,
BareCarriageReturn,
+ BareCarriageReturnInRawString,
EscapeOnlyChar,
TooShortHexEscape,
UnicodeEscapeInByte,
NonAsciiCharInByte,
+ NonAsciiCharInByteString,
}
/// Takes a contents of a char literal (without quotes), and returns an
})
}
+/// 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<F>(literal_text: &str, callback: &mut F)
+where
+ F: FnMut(Range<usize>, Result<char, EscapeError>),
+{
+ 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<F>(literal_text: &str, callback: &mut F)
+where
+ F: FnMut(Range<usize>, Result<u8, EscapeError>),
+{
+ 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,
}
}
+/// 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<F>(literal_text: &str, mode: Mode, callback: &mut F)
+where
+ F: FnMut(Range<usize>, Result<char, EscapeError>),
+{
+ 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
}
};
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();
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]")
let s = r"string\r
literal";\r
assert_eq!(s, "string\nliteral");\r
+ let s = br"byte string\r
+literal";\r
+ assert_eq!(s, "byte string\nliteral".as_bytes());\r
\r
// validate that our source file has CRLF endings\r
let source = include_str!("lexer-crlf-line-endings-string-literal-doc-comment.rs");\r
--- /dev/null
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+struct ArrayStruct<T, const N: usize> {
+ data: [T; N],
+}
+
+struct ArrayTuple<T, const N: usize>([T; N]);
+
+fn main() {
+ let _ = ArrayStruct { data: [0u32; 8] };
+ let _ = ArrayTuple([0u32; 8]);
+}
--- /dev/null
+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)]
+ | ^^^^^^^^^^^^^^
+
--- /dev/null
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+#[derive(Debug)]
+struct X<const N: usize> {
+ a: [u32; N], //~ ERROR `[u32; _]` doesn't implement `std::fmt::Debug`
+}
+
+fn main() {}
--- /dev/null
+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`.
LL | let _s = "foo\rbar";
| ^
-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\rfoo";
- | ^^^^^
+ | ^
error: unknown character escape: \r
--> $DIR/lex-bare-cr-string-literal-doc-comment.rs:27:19
+// ignore-tidy-cr
+// compile-flags: -Z continue-parse-after-error
pub fn main() {
+ br"a\r"; //~ 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
}
-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\r";
+ | ^
+
+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
--- /dev/null
+{"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"}
--- /dev/null
+// compile-pass
+// compile-flags: -Zsave-analysis -Zemit-artifact-notifications
+// compile-flags: --crate-type rlib --error-format=json
+pub fn foo() {}
--- /dev/null
+{"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"}
-Subproject commit 71be6f62fa920c0bd10cdf3a29aeb8c6719a8075
+Subproject commit c0dbd34ba99a949ece25c297a4a377685eb89c7c
-Subproject commit d1e20280dc188f542c083a738f8da3fef25af478
+Subproject commit 483dcbc73f9923e98c71ec9df11ee3d0d5cfb467