1
Fork 0

Auto merge of #99177 - Dylan-DPC:rollup-m0k9q2w, r=Dylan-DPC

Rollup of 6 pull requests

Successful merges:

 - #98622 (rustc_target: Flip the default for `TargetOptions::executables` to true)
 - #98633 (Fix last `let_chains` blocker)
 - #98972 (Suggest adding a missing zero to a floating point number)
 - #99038 (Some more `EarlyBinder` cleanups)
 - #99154 (use PlaceRef::iter_projections to fix old FIXME)
 - #99171 (Put back UI test regex)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-07-12 11:36:58 +00:00
commit 1c7b36d4db
82 changed files with 1180 additions and 427 deletions

View file

@ -1111,11 +1111,9 @@ macro_rules! visit_place_fns {
context: PlaceContext,
location: Location,
) {
// FIXME: Use PlaceRef::iter_projections, once that exists.
let mut cursor = place_ref.projection;
while let &[ref proj_base @ .., elem] = cursor {
cursor = proj_base;
self.visit_projection_elem(place_ref.local, cursor, elem, context, location);
for (base, elem) in place_ref.iter_projections().rev() {
let base_proj = base.projection;
self.visit_projection_elem(place_ref.local, base_proj, elem, context, location);
}
}

View file

@ -85,10 +85,10 @@ impl GenericParamDef {
) -> Option<EarlyBinder<ty::GenericArg<'tcx>>> {
match self.kind {
GenericParamDefKind::Type { has_default, .. } if has_default => {
Some(EarlyBinder(tcx.type_of(self.def_id).into()))
Some(tcx.bound_type_of(self.def_id).map_bound(|t| t.into()))
}
GenericParamDefKind::Const { has_default } if has_default => {
Some(EarlyBinder(tcx.const_param_default(self.def_id).into()))
Some(tcx.bound_const_param_default(self.def_id).map_bound(|c| c.into()))
}
_ => None,
}

View file

@ -932,6 +932,10 @@ impl<T> EarlyBinder<T> {
let value = f(self.0)?;
Ok(EarlyBinder(value))
}
pub fn rebind<U>(&self, value: U) -> EarlyBinder<U> {
EarlyBinder(value)
}
}
impl<T> EarlyBinder<Option<T>> {

View file

@ -676,6 +676,10 @@ impl<'tcx> TyCtxt<'tcx> {
) -> ty::EarlyBinder<&'tcx ty::List<ty::Predicate<'tcx>>> {
ty::EarlyBinder(self.item_bounds(def_id))
}
pub fn bound_const_param_default(self, def_id: DefId) -> ty::EarlyBinder<ty::Const<'tcx>> {
ty::EarlyBinder(self.const_param_default(def_id))
}
}
struct OpaqueTypeExpander<'tcx> {

View file

@ -537,13 +537,12 @@ fn build_call_shim<'tcx>(
};
let def_id = instance.def_id();
let sig = tcx.fn_sig(def_id);
let mut sig = tcx.erase_late_bound_regions(sig);
let sig = tcx.bound_fn_sig(def_id);
let sig = sig.map_bound(|sig| tcx.erase_late_bound_regions(sig));
assert_eq!(sig_substs.is_some(), !instance.has_polymorphic_mir_body());
if let Some(sig_substs) = sig_substs {
sig = EarlyBinder(sig).subst(tcx, sig_substs);
}
let mut sig =
if let Some(sig_substs) = sig_substs { sig.subst(tcx, sig_substs) } else { sig.0 };
if let CallKind::Indirect(fnty) = call_kind {
// `sig` determines our local decls, and thus the callee type in the `Call` terminator. This

View file

@ -1393,7 +1393,9 @@ impl<'a> Parser<'a> {
self.parse_yield_expr(attrs)
} else if self.is_do_yeet() {
self.parse_yeet_expr(attrs)
} else if self.eat_keyword(kw::Let) {
} else if self.check_keyword(kw::Let) {
self.manage_let_chains_context();
self.bump();
self.parse_let_expr(attrs)
} else if self.eat_keyword(kw::Underscore) {
Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore, attrs))
@ -2355,16 +2357,30 @@ impl<'a> Parser<'a> {
Ok(cond)
}
// Checks if `let` is in an invalid position like `let x = let y = 1;` or
// if the current `let` is in a let_chains context but nested in another
// expression like `if let Some(_) = _opt && [1, 2, 3][let _ = ()] = 1`.
//
// This method expects that the current token is `let`.
fn manage_let_chains_context(&mut self) {
debug_assert!(matches!(self.token.kind, TokenKind::Ident(kw::Let, _)));
let is_in_a_let_chains_context_but_nested_in_other_expr = self.let_expr_allowed
&& !matches!(
self.prev_token.kind,
TokenKind::AndAnd
| TokenKind::CloseDelim(Delimiter::Brace)
| TokenKind::Ident(kw::If, _)
| TokenKind::Ident(kw::While, _)
);
if !self.let_expr_allowed || is_in_a_let_chains_context_but_nested_in_other_expr {
self.struct_span_err(self.token.span, "expected expression, found `let` statement")
.emit();
}
}
/// Parses a `let $pat = $expr` pseudo-expression.
/// The `let` token has already been eaten.
fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
if !self.let_expr_allowed {
self.struct_span_err(
self.prev_token.span,
"expected expression, found `let` statement",
)
.emit();
}
let lo = self.prev_token.span;
let pat = self.parse_pat_allow_top_alt(
None,

View file

@ -13,7 +13,6 @@ pub fn target() -> Target {
linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
linker: Some("rust-lld".into()),
features: "+strict-align,+neon,+fp-armv8".into(),
executables: true,
relocation_model: RelocModel::Static,
disable_redzone: true,
max_atomic_width: Some(128),

View file

@ -14,7 +14,6 @@ pub fn target() -> Target {
linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
linker: Some("rust-lld".into()),
features: "+strict-align,-neon,-fp-armv8".into(),
executables: true,
relocation_model: RelocModel::Static,
disable_redzone: true,
max_atomic_width: Some(128),

View file

@ -25,7 +25,6 @@ pub fn opts(os: &'static str) -> TargetOptions {
function_sections: false,
dynamic_linking: true,
linker_is_gnu: false,
executables: true,
families: cvs!["unix"],
is_like_osx: true,
default_dwarf_version: 2,

View file

@ -54,7 +54,6 @@ pub fn opts(os: &'static str, arch: Arch) -> TargetOptions {
abi: target_abi(arch).into(),
cpu: target_cpu(arch).into(),
dynamic_linking: false,
executables: true,
link_env_remove: link_env_remove(arch),
has_thread_local: false,
..super::apple_base::opts(os)

View file

@ -14,7 +14,6 @@ pub fn target() -> Target {
abi: "eabi".into(),
endian: Endian::Big,
linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
executables: true,
linker: Some("rust-lld".into()),
relocation_model: RelocModel::Static,
panic_strategy: PanicStrategy::Abort,

View file

@ -14,7 +14,6 @@ pub fn target() -> Target {
abi: "eabihf".into(),
endian: Endian::Big,
linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
executables: true,
linker: Some("rust-lld".into()),
relocation_model: RelocModel::Static,
panic_strategy: PanicStrategy::Abort,

View file

@ -23,7 +23,6 @@ pub fn target() -> Target {
abi: "eabihf".into(),
linker_flavor: LinkerFlavor::Gcc,
cpu: "mpcore".into(),
executables: true,
families: cvs!["unix"],
linker: Some("arm-none-eabi-gcc".into()),
relocation_model: RelocModel::Static,

View file

@ -22,7 +22,6 @@ pub fn target() -> Target {
linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
linker: Some("rust-lld".into()),
features: "+v7,+thumb2,+soft-float,-neon,+strict-align".into(),
executables: true,
relocation_model: RelocModel::Static,
disable_redzone: true,
max_atomic_width: Some(64),

View file

@ -13,7 +13,6 @@ pub fn target() -> Target {
linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
linker: Some("rust-lld".into()),
features: "+v7,+vfp3,-d32,+thumb2,-neon,+strict-align".into(),
executables: true,
relocation_model: RelocModel::Static,
disable_redzone: true,
max_atomic_width: Some(64),

View file

@ -13,7 +13,6 @@ pub fn target() -> Target {
options: TargetOptions {
abi: "eabi".into(),
linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
executables: true,
linker: Some("rust-lld".into()),
relocation_model: RelocModel::Static,
panic_strategy: PanicStrategy::Abort,

View file

@ -13,7 +13,6 @@ pub fn target() -> Target {
options: TargetOptions {
abi: "eabihf".into(),
linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
executables: true,
linker: Some("rust-lld".into()),
relocation_model: RelocModel::Static,
panic_strategy: PanicStrategy::Abort,

View file

@ -16,7 +16,6 @@ pub fn target(target_cpu: &'static str, mmcu: &'static str) -> Target {
exe_suffix: ".elf".into(),
linker: Some("avr-gcc".into()),
executables: true,
eh_frame_header: false,
pre_link_args: TargetOptions::link_args(LinkerFlavor::Gcc, &[mmcu]),
late_link_args: TargetOptions::link_args(LinkerFlavor::Gcc, &["-lgcc"]),

View file

@ -7,7 +7,6 @@ pub fn opts(endian: Endian) -> TargetOptions {
endian,
linker_flavor: LinkerFlavor::BpfLinker,
atomic_cas: false,
executables: true,
dynamic_linking: true,
no_builtins: true,
panic_strategy: PanicStrategy::Abort,

View file

@ -4,7 +4,6 @@ pub fn opts() -> TargetOptions {
TargetOptions {
os: "dragonfly".into(),
dynamic_linking: true,
executables: true,
families: cvs!["unix"],
has_rpath: true,
position_independent_executables: true,

View file

@ -4,7 +4,6 @@ pub fn opts() -> TargetOptions {
TargetOptions {
os: "freebsd".into(),
dynamic_linking: true,
executables: true,
families: cvs!["unix"],
has_rpath: true,
position_independent_executables: true,

View file

@ -23,7 +23,6 @@ pub fn opts() -> TargetOptions {
linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
linker: Some("rust-lld".into()),
dynamic_linking: true,
executables: true,
families: cvs!["unix"],
pre_link_args,
pre_link_objects: crt_objects::new(&[

View file

@ -4,7 +4,6 @@ pub fn opts() -> TargetOptions {
TargetOptions {
os: "haiku".into(),
dynamic_linking: true,
executables: true,
families: cvs!["unix"],
relro_level: RelroLevel::Full,
..Default::default()

View file

@ -10,7 +10,6 @@ pub fn opts() -> TargetOptions {
os: "hermit".into(),
linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
linker: Some("rust-lld".into()),
executables: true,
has_thread_local: true,
pre_link_args,
panic_strategy: PanicStrategy::Abort,

View file

@ -11,7 +11,6 @@ pub fn target() -> Target {
base.has_rpath = true;
base.linker_is_gnu = false;
base.dynamic_linking = true;
base.executables = true;
base.c_enum_min_bits = 8;

View file

@ -27,7 +27,6 @@ pub fn opts() -> TargetOptions {
TargetOptions {
os: "illumos".into(),
dynamic_linking: true,
executables: true,
has_rpath: true,
families: cvs!["unix"],
is_like_solaris: true,

View file

@ -5,7 +5,6 @@ pub fn opts() -> TargetOptions {
os: "l4re".into(),
env: "uclibc".into(),
linker_flavor: LinkerFlavor::L4Bender,
executables: true,
panic_strategy: PanicStrategy::Abort,
linker: Some("l4-bender".into()),
linker_is_gnu: false,

View file

@ -4,7 +4,6 @@ pub fn opts() -> TargetOptions {
TargetOptions {
os: "linux".into(),
dynamic_linking: true,
executables: true,
families: cvs!["unix"],
has_rpath: true,
position_independent_executables: true,

View file

@ -18,7 +18,6 @@ pub fn target() -> Target {
vendor: "sony".into(),
linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
cpu: "mips2".into(),
executables: true,
linker: Some("rust-lld".into()),
relocation_model: RelocModel::Static,

View file

@ -17,7 +17,6 @@ pub fn target() -> Target {
cpu: "mips32r2".into(),
features: "+mips32r2,+soft-float,+noabicalls".into(),
max_atomic_width: Some(32),
executables: true,
linker: Some("rust-lld".into()),
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,

View file

@ -1212,8 +1212,7 @@ pub struct TargetOptions {
pub dynamic_linking: bool,
/// If dynamic linking is available, whether only cdylibs are supported.
pub only_cdylib: bool,
/// Whether executables are available on this target. iOS, for example, only allows static
/// libraries. Defaults to false.
/// Whether executables are available on this target. Defaults to true.
pub executables: bool,
/// Relocation model to use in object file. Corresponds to `llc
/// -relocation-model=$relocation_model`. Defaults to `Pic`.
@ -1520,7 +1519,7 @@ impl Default for TargetOptions {
features: "".into(),
dynamic_linking: false,
only_cdylib: false,
executables: false,
executables: true,
relocation_model: RelocModel::Pic,
code_model: None,
tls_model: TlsModel::GeneralDynamic,

View file

@ -9,7 +9,6 @@ pub fn target() -> Target {
options: TargetOptions {
c_int_width: "16".into(),
executables: true,
// The LLVM backend currently can't generate object files. To
// workaround this LLVM generates assembly files which then we feed

View file

@ -7,7 +7,6 @@ pub fn opts() -> TargetOptions {
TargetOptions {
linker_flavor: LinkerFlavor::Msvc,
executables: true,
is_like_windows: true,
is_like_msvc: true,
lld_flavor: LldFlavor::Link,

View file

@ -4,7 +4,6 @@ pub fn opts() -> TargetOptions {
TargetOptions {
os: "netbsd".into(),
dynamic_linking: true,
executables: true,
families: cvs!["unix"],
no_default_libraries: false,
has_rpath: true,

View file

@ -26,7 +26,6 @@ pub fn target() -> Target {
// Needed to use `dylib` and `bin` crate types and the linker.
dynamic_linking: true,
executables: true,
// Avoid using dylib because it contain metadata not supported
// by LLVM NVPTX backend.

View file

@ -4,7 +4,6 @@ pub fn opts() -> TargetOptions {
TargetOptions {
os: "openbsd".into(),
dynamic_linking: true,
executables: true,
families: cvs!["unix"],
has_rpath: true,
abi_return_struct_as_int: true,

View file

@ -5,7 +5,6 @@ pub fn opts() -> TargetOptions {
os: "redox".into(),
env: "relibc".into(),
dynamic_linking: true,
executables: true,
families: cvs!["unix"],
has_rpath: true,
position_independent_executables: true,

View file

@ -14,7 +14,6 @@ pub fn target() -> Target {
cpu: "generic-rv32".into(),
max_atomic_width: Some(0),
atomic_cas: false,
executables: true,
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
emit_debug_gdb_scripts: false,

View file

@ -15,7 +15,6 @@ pub fn target() -> Target {
max_atomic_width: Some(0),
atomic_cas: false,
features: "+m".into(),
executables: true,
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
emit_debug_gdb_scripts: false,

View file

@ -14,7 +14,6 @@ pub fn target() -> Target {
cpu: "generic-rv32".into(),
max_atomic_width: Some(32),
features: "+m,+a,+c".into(),
executables: true,
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
emit_debug_gdb_scripts: false,

View file

@ -15,7 +15,6 @@ pub fn target() -> Target {
cpu: "generic-rv32".into(),
max_atomic_width: Some(32),
features: "+m,+a,+c".into(),
executables: true,
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
..Default::default()

View file

@ -26,7 +26,6 @@ pub fn target() -> Target {
atomic_cas: true,
features: "+m,+c".into(),
executables: true,
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
emit_debug_gdb_scripts: false,

View file

@ -15,7 +15,6 @@ pub fn target() -> Target {
max_atomic_width: Some(0),
atomic_cas: false,
features: "+m,+c".into(),
executables: true,
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
emit_debug_gdb_scripts: false,

View file

@ -15,7 +15,6 @@ pub fn target() -> Target {
cpu: "generic-rv64".into(),
max_atomic_width: Some(64),
features: "+m,+a,+f,+d,+c".into(),
executables: true,
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
code_model: Some(CodeModel::Medium),

View file

@ -14,7 +14,6 @@ pub fn target() -> Target {
cpu: "generic-rv64".into(),
max_atomic_width: Some(64),
features: "+m,+a,+c".into(),
executables: true,
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
code_model: Some(CodeModel::Medium),

View file

@ -4,7 +4,6 @@ pub fn opts() -> TargetOptions {
TargetOptions {
os: "solaris".into(),
dynamic_linking: true,
executables: true,
has_rpath: true,
families: cvs!["unix"],
is_like_solaris: true,

View file

@ -5,6 +5,7 @@ pub fn opts(kernel: &str) -> TargetOptions {
TargetOptions {
os: format!("solid_{}", kernel).into(),
vendor: "kmc".into(),
executables: false,
frame_pointer: FramePointer::NonLeaf,
has_thread_local: true,
..Default::default()

View file

@ -34,7 +34,6 @@ pub fn opts() -> TargetOptions {
// See rust-lang/rfcs#1645 for a discussion about these defaults
TargetOptions {
linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
executables: true,
// In most cases, LLD is good enough
linker: Some("rust-lld".into()),
// Because these devices have very little resources having an unwinder is too onerous so we

View file

@ -8,7 +8,6 @@ pub fn opts() -> TargetOptions {
linker: Some("wr-c++".into()),
exe_suffix: ".vxe".into(),
dynamic_linking: true,
executables: true,
families: cvs!["unix"],
has_rpath: true,
has_thread_local: true,

View file

@ -62,9 +62,6 @@ pub fn options() -> TargetOptions {
dynamic_linking: true,
only_cdylib: true,
// This means we'll just embed a `#[start]` function in the wasm module
executables: true,
// relatively self-explanatory!
exe_suffix: ".wasm".into(),
dll_prefix: "".into(),

View file

@ -67,7 +67,6 @@ pub fn opts() -> TargetOptions {
function_sections: false,
linker: Some("gcc".into()),
dynamic_linking: true,
executables: true,
dll_prefix: "".into(),
dll_suffix: ".dll".into(),
exe_suffix: ".exe".into(),

View file

@ -20,7 +20,6 @@ pub fn opts() -> TargetOptions {
abi: "llvm".into(),
linker: Some("clang".into()),
dynamic_linking: true,
executables: true,
dll_prefix: "".into(),
dll_suffix: ".dll".into(),
exe_suffix: ".exe".into(),

View file

@ -24,7 +24,6 @@ pub fn opts() -> TargetOptions {
TargetOptions {
abi: "uwp".into(),
vendor: "uwp".into(),
executables: false,
limit_rdylib_exports: false,
late_link_args,
late_link_args_dynamic,

View file

@ -62,7 +62,6 @@ pub fn target() -> Target {
vendor: "fortanix".into(),
abi: "fortanix".into(),
linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
executables: true,
linker: Some("rust-lld".into()),
max_atomic_width: Some(64),
cpu: "x86-64".into(),

View file

@ -24,7 +24,6 @@ pub fn target() -> Target {
features:
"-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
.into(),
executables: true,
disable_redzone: true,
panic_strategy: PanicStrategy::Abort,
code_model: Some(CodeModel::Kernel),

View file

@ -12,7 +12,7 @@ use rustc_index::bit_set::GrowableBitSet;
use rustc_infer::infer::InferOk;
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef};
use rustc_middle::ty::{self, EarlyBinder, GenericParamDefKind, Ty, TyCtxt};
use rustc_middle::ty::{self, GenericParamDefKind, Ty, TyCtxt};
use rustc_middle::ty::{ToPolyTraitRef, ToPredicate};
use rustc_span::def_id::DefId;
@ -555,7 +555,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter());
let bound =
EarlyBinder(bound.0.kind().skip_binder()).subst(tcx, assoc_ty_substs);
bound.map_bound(|b| b.kind().skip_binder()).subst(tcx, assoc_ty_substs);
tcx.mk_predicate(ty::Binder::bind_with_vars(bound, bound_vars))
};
let normalized_bound = normalize_with_depth_to(

View file

@ -550,7 +550,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
GenericParamDefKind::Const { has_default } => {
let ty = tcx.at(self.span).type_of(param.def_id);
if !infer_args && has_default {
EarlyBinder(tcx.const_param_default(param.def_id))
tcx.bound_const_param_default(param.def_id)
.subst(tcx, substs.unwrap())
.into()
} else {

View file

@ -48,7 +48,7 @@ use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TypeVisitable};
use rustc_session::parse::feature_err;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::source_map::Span;
use rustc_span::source_map::{Span, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, Pos};
use rustc_target::spec::abi::Abi::RustIntrinsic;
@ -2162,14 +2162,55 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else if !expr_t.is_primitive_ty() {
self.ban_nonexisting_field(field, base, expr, expr_t);
} else {
type_error_struct!(
let field_name = field.to_string();
let mut err = type_error_struct!(
self.tcx().sess,
field.span,
expr_t,
E0610,
"`{expr_t}` is a primitive type and therefore doesn't have fields",
)
.emit();
);
let is_valid_suffix = |field: String| {
if field == "f32" || field == "f64" {
return true;
}
let mut chars = field.chars().peekable();
match chars.peek() {
Some('e') | Some('E') => {
chars.next();
if let Some(c) = chars.peek()
&& !c.is_numeric() && *c != '-' && *c != '+'
{
return false;
}
while let Some(c) = chars.peek() {
if !c.is_numeric() {
break;
}
chars.next();
}
}
_ => (),
}
let suffix = chars.collect::<String>();
suffix.is_empty() || suffix == "f32" || suffix == "f64"
};
if let ty::Infer(ty::IntVar(_)) = expr_t.kind()
&& let ExprKind::Lit(Spanned {
node: ast::LitKind::Int(_, ast::LitIntType::Unsuffixed),
..
}) = base.kind
&& !base.span.from_expansion()
&& is_valid_suffix(field_name)
{
err.span_suggestion_verbose(
field.span.shrink_to_lo(),
"If the number is meant to be a floating point number, consider adding a `0` after the period",
'0',
Applicability::MaybeIncorrect,
);
}
err.emit();
}
self.tcx().ty_error()

View file

@ -1426,7 +1426,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
GenericParamDefKind::Const { has_default } => {
if !infer_args && has_default {
EarlyBinder(tcx.const_param_default(param.def_id))
tcx.bound_const_param_default(param.def_id)
.subst(tcx, substs.unwrap())
.into()
} else {

View file

@ -21,9 +21,7 @@ use rustc_middle::middle::stability;
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
use rustc_middle::ty::GenericParamDefKind;
use rustc_middle::ty::{
self, EarlyBinder, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitable,
};
use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitable};
use rustc_session::lint;
use rustc_span::def_id::LocalDefId;
use rustc_span::lev_distance::{
@ -713,7 +711,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id);
let impl_ty = EarlyBinder(impl_ty).subst(self.tcx, impl_substs);
let impl_ty = impl_ty.subst(self.tcx, impl_substs);
debug!("impl_ty: {:?}", impl_ty);
@ -1811,9 +1809,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
self.erase_late_bound_regions(xform_fn_sig)
}
/// Gets the type of an impl and generate substitutions with placeholders.
fn impl_ty_and_substs(&self, impl_def_id: DefId) -> (Ty<'tcx>, SubstsRef<'tcx>) {
(self.tcx.type_of(impl_def_id), self.fresh_item_substs(impl_def_id))
/// Gets the type of an impl and generate substitutions with inference vars.
fn impl_ty_and_substs(
&self,
impl_def_id: DefId,
) -> (ty::EarlyBinder<Ty<'tcx>>, SubstsRef<'tcx>) {
(self.tcx.bound_type_of(impl_def_id), self.fresh_item_substs(impl_def_id))
}
fn fresh_item_substs(&self, def_id: DefId) -> SubstsRef<'tcx> {

View file

@ -6,7 +6,7 @@ use super::utils::*;
#[derive(Debug)]
pub struct ExplicitPredicatesMap<'tcx> {
map: FxHashMap<DefId, RequiredPredicates<'tcx>>,
map: FxHashMap<DefId, ty::EarlyBinder<RequiredPredicates<'tcx>>>,
}
impl<'tcx> ExplicitPredicatesMap<'tcx> {
@ -14,11 +14,11 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
ExplicitPredicatesMap { map: FxHashMap::default() }
}
pub fn explicit_predicates_of(
pub(crate) fn explicit_predicates_of(
&mut self,
tcx: TyCtxt<'tcx>,
def_id: DefId,
) -> &RequiredPredicates<'tcx> {
) -> &ty::EarlyBinder<RequiredPredicates<'tcx>> {
self.map.entry(def_id).or_insert_with(|| {
let predicates = if def_id.is_local() {
tcx.explicit_predicates_of(def_id)
@ -63,7 +63,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
}
}
required_predicates
ty::EarlyBinder(required_predicates)
})
}
}

View file

@ -2,7 +2,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::Span;
use super::explicit::ExplicitPredicatesMap;
@ -13,20 +13,19 @@ use super::utils::*;
/// `global_inferred_outlives`: this is initially the empty map that
/// was generated by walking the items in the crate. This will
/// now be filled with inferred predicates.
pub fn infer_predicates<'tcx>(
pub(super) fn infer_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
explicit_map: &mut ExplicitPredicatesMap<'tcx>,
) -> FxHashMap<DefId, RequiredPredicates<'tcx>> {
) -> FxHashMap<DefId, ty::EarlyBinder<RequiredPredicates<'tcx>>> {
debug!("infer_predicates");
let mut predicates_added = true;
let mut explicit_map = ExplicitPredicatesMap::new();
let mut global_inferred_outlives = FxHashMap::default();
// If new predicates were added then we need to re-calculate
// all crates since there could be new implied predicates.
while predicates_added {
predicates_added = false;
'outer: loop {
let mut predicates_added = false;
// Visit all the crates and infer predicates
for id in tcx.hir().items() {
@ -53,9 +52,9 @@ pub fn infer_predicates<'tcx>(
tcx,
field_ty,
field_span,
&mut global_inferred_outlives,
&global_inferred_outlives,
&mut item_required_predicates,
explicit_map,
&mut explicit_map,
);
}
}
@ -70,12 +69,17 @@ pub fn infer_predicates<'tcx>(
// we walk the crates again and re-calculate predicates for all
// items.
let item_predicates_len: usize =
global_inferred_outlives.get(&item_did.to_def_id()).map_or(0, |p| p.len());
global_inferred_outlives.get(&item_did.to_def_id()).map_or(0, |p| p.0.len());
if item_required_predicates.len() > item_predicates_len {
predicates_added = true;
global_inferred_outlives.insert(item_did.to_def_id(), item_required_predicates);
global_inferred_outlives
.insert(item_did.to_def_id(), ty::EarlyBinder(item_required_predicates));
}
}
if !predicates_added {
break 'outer;
}
}
global_inferred_outlives
@ -85,7 +89,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
tcx: TyCtxt<'tcx>,
field_ty: Ty<'tcx>,
field_span: Span,
global_inferred_outlives: &FxHashMap<DefId, RequiredPredicates<'tcx>>,
global_inferred_outlives: &FxHashMap<DefId, ty::EarlyBinder<RequiredPredicates<'tcx>>>,
required_predicates: &mut RequiredPredicates<'tcx>,
explicit_map: &mut ExplicitPredicatesMap<'tcx>,
) {
@ -133,11 +137,13 @@ fn insert_required_predicates_to_be_wf<'tcx>(
// 'a` holds for `Foo`.
debug!("Adt");
if let Some(unsubstituted_predicates) = global_inferred_outlives.get(&def.did()) {
for (unsubstituted_predicate, &span) in unsubstituted_predicates {
for (unsubstituted_predicate, &span) in &unsubstituted_predicates.0 {
// `unsubstituted_predicate` is `U: 'b` in the
// example above. So apply the substitution to
// get `T: 'a` (or `predicate`):
let predicate = EarlyBinder(*unsubstituted_predicate).subst(tcx, substs);
let predicate = unsubstituted_predicates
.rebind(*unsubstituted_predicate)
.subst(tcx, substs);
insert_outlives_predicate(
tcx,
predicate.0,
@ -224,7 +230,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
/// will give us `U: 'static` and `U: Foo`. The latter we
/// can ignore, but we will want to process `U: 'static`,
/// applying the substitution as above.
pub fn check_explicit_predicates<'tcx>(
fn check_explicit_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
substs: &[GenericArg<'tcx>],
@ -242,7 +248,7 @@ pub fn check_explicit_predicates<'tcx>(
);
let explicit_predicates = explicit_map.explicit_predicates_of(tcx, def_id);
for (outlives_predicate, &span) in explicit_predicates {
for (outlives_predicate, &span) in &explicit_predicates.0 {
debug!("outlives_predicate = {:?}", &outlives_predicate);
// Careful: If we are inferring the effects of a `dyn Trait<..>`
@ -287,7 +293,7 @@ pub fn check_explicit_predicates<'tcx>(
continue;
}
let predicate = EarlyBinder(*outlives_predicate).subst(tcx, substs);
let predicate = explicit_predicates.rebind(*outlives_predicate).subst(tcx, substs);
debug!("predicate = {:?}", &predicate);
insert_outlives_predicate(tcx, predicate.0, predicate.1, span, required_predicates);
}

View file

@ -88,9 +88,7 @@ fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> {
// for the type.
// Compute the inferred predicates
let mut exp_map = explicit::ExplicitPredicatesMap::new();
let global_inferred_outlives = implicit_infer::infer_predicates(tcx, &mut exp_map);
let global_inferred_outlives = implicit_infer::infer_predicates(tcx);
// Convert the inferred predicates into the "collected" form the
// global data structure expects.
@ -100,7 +98,7 @@ fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> {
let predicates = global_inferred_outlives
.iter()
.map(|(&def_id, set)| {
let predicates = &*tcx.arena.alloc_from_iter(set.iter().filter_map(
let predicates = &*tcx.arena.alloc_from_iter(set.0.iter().filter_map(
|(ty::OutlivesPredicate(kind1, region2), &span)| {
match kind1.unpack() {
GenericArgKind::Type(ty1) => Some((

View file

@ -7,12 +7,12 @@ use std::collections::BTreeMap;
/// Tracks the `T: 'a` or `'a: 'a` predicates that we have inferred
/// must be added to the struct header.
pub type RequiredPredicates<'tcx> =
pub(crate) type RequiredPredicates<'tcx> =
BTreeMap<ty::OutlivesPredicate<GenericArg<'tcx>, ty::Region<'tcx>>, Span>;
/// Given a requirement `T: 'a` or `'b: 'a`, deduce the
/// outlives_component and add it to `required_predicates`
pub fn insert_outlives_predicate<'tcx>(
pub(crate) fn insert_outlives_predicate<'tcx>(
tcx: TyCtxt<'tcx>,
kind: GenericArg<'tcx>,
outlived_region: Region<'tcx>,

View file

@ -8,4 +8,4 @@ all:
RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=my-x86_64-unknown-linux-gnu-platform --crate-type=lib --emit=asm
$(RUSTC) -Z unstable-options --target=my-awesome-platform.json --print target-spec-json > $(TMPDIR)/test-platform.json && $(RUSTC) -Z unstable-options --target=$(TMPDIR)/test-platform.json --print target-spec-json | diff -q $(TMPDIR)/test-platform.json -
$(RUSTC) foo.rs --target=definitely-not-builtin-target 2>&1 | $(CGREP) 'may not set is_builtin'
$(RUSTC) foo.rs --target=mismatching-data-layout
$(RUSTC) foo.rs --target=mismatching-data-layout --crate-type=lib

View file

@ -1,4 +1,6 @@
// check-pass
// compile-flags: -Chelp
// check-stdout
// regex-error-pattern: -C\s+incremental
pub struct Foo;

View file

@ -1,4 +1,6 @@
// check-pass
// compile-flags: -Zhelp
// check-stdout
// regex-error-pattern: -Z\s+self-profile
pub struct Foo;

View file

@ -9,9 +9,11 @@ fn _if_let_guard() {
() if (let 0 = 1) => {}
//~^ ERROR `let` expressions in this position are unstable
//~| ERROR expected expression, found `let` statement
() if (((let 0 = 1))) => {}
//~^ ERROR `let` expressions in this position are unstable
//~| ERROR expected expression, found `let` statement
() if true && let 0 = 1 => {}
//~^ ERROR `if let` guards are experimental
@ -23,13 +25,17 @@ fn _if_let_guard() {
() if (let 0 = 1) && true => {}
//~^ ERROR `let` expressions in this position are unstable
//~| ERROR expected expression, found `let` statement
() if true && (let 0 = 1) => {}
//~^ ERROR `let` expressions in this position are unstable
//~| ERROR expected expression, found `let` statement
() if (let 0 = 1) && (let 0 = 1) => {}
//~^ ERROR `let` expressions in this position are unstable
//~| ERROR `let` expressions in this position are unstable
//~| ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
() if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
//~^ ERROR `if let` guards are experimental
@ -38,6 +44,7 @@ fn _if_let_guard() {
//~| ERROR `let` expressions in this position are unstable
//~| ERROR `let` expressions in this position are unstable
//~| ERROR `let` expressions in this position are unstable
//~| ERROR expected expression, found `let` statement
() if let Range { start: _, end: _ } = (true..true) && false => {}
//~^ ERROR `if let` guards are experimental

View file

@ -1,17 +1,59 @@
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:59:16
--> $DIR/feature-gate.rs:10:16
|
LL | () if (let 0 = 1) => {}
| ^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:14:18
|
LL | () if (((let 0 = 1))) => {}
| ^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:26:16
|
LL | () if (let 0 = 1) && true => {}
| ^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:30:24
|
LL | () if true && (let 0 = 1) => {}
| ^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:34:16
|
LL | () if (let 0 = 1) && (let 0 = 1) => {}
| ^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:34:31
|
LL | () if (let 0 = 1) && (let 0 = 1) => {}
| ^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:40:42
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:66:16
|
LL | use_expr!((let 0 = 1 && 0 == 0));
| ^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:62:16
--> $DIR/feature-gate.rs:69:16
|
LL | use_expr!((let 0 = 1));
| ^^^
error: no rules expected the token `let`
--> $DIR/feature-gate.rs:71:15
--> $DIR/feature-gate.rs:78:15
|
LL | macro_rules! use_expr {
| --------------------- when calling this macro
@ -30,7 +72,7 @@ LL | () if let 0 = 1 => {}
= help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
error[E0658]: `if let` guards are experimental
--> $DIR/feature-gate.rs:16:12
--> $DIR/feature-gate.rs:18:12
|
LL | () if true && let 0 = 1 => {}
| ^^^^^^^^^^^^^^^^^^^^
@ -40,7 +82,7 @@ LL | () if true && let 0 = 1 => {}
= help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
error[E0658]: `if let` guards are experimental
--> $DIR/feature-gate.rs:20:12
--> $DIR/feature-gate.rs:22:12
|
LL | () if let 0 = 1 && true => {}
| ^^^^^^^^^^^^^^^^^^^^
@ -50,7 +92,7 @@ LL | () if let 0 = 1 && true => {}
= help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
error[E0658]: `if let` guards are experimental
--> $DIR/feature-gate.rs:34:12
--> $DIR/feature-gate.rs:40:12
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -60,7 +102,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
= help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
error[E0658]: `if let` guards are experimental
--> $DIR/feature-gate.rs:42:12
--> $DIR/feature-gate.rs:49:12
|
LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -70,7 +112,7 @@ LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
= help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
error[E0658]: `if let` guards are experimental
--> $DIR/feature-gate.rs:67:12
--> $DIR/feature-gate.rs:74:12
|
LL | () if let 0 = 1 => {}
| ^^^^^^^^^^^^
@ -89,7 +131,7 @@ LL | () if (let 0 = 1) => {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:13:18
--> $DIR/feature-gate.rs:14:18
|
LL | () if (((let 0 = 1))) => {}
| ^^^^^^^^^
@ -98,7 +140,7 @@ LL | () if (((let 0 = 1))) => {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:16:23
--> $DIR/feature-gate.rs:18:23
|
LL | () if true && let 0 = 1 => {}
| ^^^^^^^^^
@ -107,7 +149,7 @@ LL | () if true && let 0 = 1 => {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:20:15
--> $DIR/feature-gate.rs:22:15
|
LL | () if let 0 = 1 && true => {}
| ^^^^^^^^^
@ -116,7 +158,7 @@ LL | () if let 0 = 1 && true => {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:24:16
--> $DIR/feature-gate.rs:26:16
|
LL | () if (let 0 = 1) && true => {}
| ^^^^^^^^^
@ -125,7 +167,7 @@ LL | () if (let 0 = 1) && true => {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:27:24
--> $DIR/feature-gate.rs:30:24
|
LL | () if true && (let 0 = 1) => {}
| ^^^^^^^^^
@ -134,7 +176,7 @@ LL | () if true && (let 0 = 1) => {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:30:16
--> $DIR/feature-gate.rs:34:16
|
LL | () if (let 0 = 1) && (let 0 = 1) => {}
| ^^^^^^^^^
@ -143,7 +185,7 @@ LL | () if (let 0 = 1) && (let 0 = 1) => {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:30:31
--> $DIR/feature-gate.rs:34:31
|
LL | () if (let 0 = 1) && (let 0 = 1) => {}
| ^^^^^^^^^
@ -152,7 +194,7 @@ LL | () if (let 0 = 1) && (let 0 = 1) => {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:34:15
--> $DIR/feature-gate.rs:40:15
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^
@ -161,7 +203,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:34:28
--> $DIR/feature-gate.rs:40:28
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^
@ -170,7 +212,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:34:42
--> $DIR/feature-gate.rs:40:42
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^
@ -179,7 +221,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:34:55
--> $DIR/feature-gate.rs:40:55
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^
@ -188,7 +230,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:34:68
--> $DIR/feature-gate.rs:40:68
|
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
| ^^^^^^^^^
@ -197,7 +239,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:42:15
--> $DIR/feature-gate.rs:49:15
|
LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -206,7 +248,7 @@ LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:59:16
--> $DIR/feature-gate.rs:66:16
|
LL | use_expr!((let 0 = 1 && 0 == 0));
| ^^^^^^^^^
@ -215,7 +257,7 @@ LL | use_expr!((let 0 = 1 && 0 == 0));
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:62:16
--> $DIR/feature-gate.rs:69:16
|
LL | use_expr!((let 0 = 1));
| ^^^^^^^^^
@ -223,6 +265,6 @@ LL | use_expr!((let 0 = 1));
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error: aborting due to 25 previous errors
error: aborting due to 32 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -28,47 +28,61 @@ fn main() {}
fn _if() {
if (let 0 = 1) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
if (((let 0 = 1))) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
if (let 0 = 1) && true {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
if true && (let 0 = 1) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
if (let 0 = 1) && (let 0 = 1) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR `let` expressions are not supported here
//~| ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
}
fn _while() {
while (let 0 = 1) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
while (((let 0 = 1))) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
while (let 0 = 1) && true {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
while true && (let 0 = 1) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
while (let 0 = 1) && (let 0 = 1) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR `let` expressions are not supported here
//~| ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
}
fn _macros() {
@ -89,39 +103,64 @@ fn _macros() {
}
fn nested_within_if_expr() {
if &let 0 = 0 {} //~ ERROR `let` expressions are not supported here
//~^ ERROR mismatched types
if &let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
if !let 0 = 0 {} //~ ERROR `let` expressions are not supported here
if *let 0 = 0 {} //~ ERROR `let` expressions are not supported here
//~^ ERROR type `bool` cannot be dereferenced
if -let 0 = 0 {} //~ ERROR `let` expressions are not supported here
//~^ ERROR cannot apply unary operator `-` to type `bool`
if !let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
if *let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR type `bool` cannot be dereferenced
//~| ERROR expected expression, found `let` statement
if -let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR cannot apply unary operator `-` to type `bool`
//~| ERROR expected expression, found `let` statement
fn _check_try_binds_tighter() -> Result<(), ()> {
if let 0 = 0? {}
//~^ ERROR the `?` operator can only be applied to values that implement `Try`
Ok(())
}
if (let 0 = 0)? {} //~ ERROR `let` expressions are not supported here
//~^ ERROR the `?` operator can only be applied to values that implement `Try`
if (let 0 = 0)? {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR the `?` operator can only be applied to values that implement `Try`
//~| ERROR the `?` operator can only be used in a function that returns `Result`
//~| ERROR expected expression, found `let` statement
if true || let 0 = 0 {} //~ ERROR `let` expressions are not supported here
if (true || let 0 = 0) {} //~ ERROR `let` expressions are not supported here
if true && (true || let 0 = 0) {} //~ ERROR `let` expressions are not supported here
if true || (true && let 0 = 0) {} //~ ERROR `let` expressions are not supported here
if true || let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
if (true || let 0 = 0) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
if true && (true || let 0 = 0) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
if true || (true && let 0 = 0) {}
//~^ ERROR `let` expressions are not supported here
let mut x = true;
if x = let 0 = 0 {} //~ ERROR `let` expressions are not supported here
//~^ ERROR mismatched types
if x = let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
if true..(let 0 = 0) {} //~ ERROR `let` expressions are not supported here
//~^ ERROR mismatched types
if ..(let 0 = 0) {} //~ ERROR `let` expressions are not supported here
//~^ ERROR mismatched types
if (let 0 = 0).. {} //~ ERROR `let` expressions are not supported here
//~^ ERROR mismatched types
if true..(let 0 = 0) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
if ..(let 0 = 0) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
if (let 0 = 0).. {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
// Binds as `(let ... = true)..true &&/|| false`.
if let Range { start: _, end: _ } = true..true && false {}
@ -151,42 +190,68 @@ fn nested_within_if_expr() {
if let true = let true = true {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
}
fn nested_within_while_expr() {
while &let 0 = 0 {} //~ ERROR `let` expressions are not supported here
//~^ ERROR mismatched types
while &let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
while !let 0 = 0 {} //~ ERROR `let` expressions are not supported here
while *let 0 = 0 {} //~ ERROR `let` expressions are not supported here
//~^ ERROR type `bool` cannot be dereferenced
while -let 0 = 0 {} //~ ERROR `let` expressions are not supported here
//~^ ERROR cannot apply unary operator `-` to type `bool`
while !let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
while *let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR type `bool` cannot be dereferenced
//~| ERROR expected expression, found `let` statement
while -let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR cannot apply unary operator `-` to type `bool`
//~| ERROR expected expression, found `let` statement
fn _check_try_binds_tighter() -> Result<(), ()> {
while let 0 = 0? {}
//~^ ERROR the `?` operator can only be applied to values that implement `Try`
Ok(())
}
while (let 0 = 0)? {} //~ ERROR `let` expressions are not supported here
//~^ ERROR the `?` operator can only be applied to values that implement `Try`
while (let 0 = 0)? {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR the `?` operator can only be applied to values that implement `Try`
//~| ERROR the `?` operator can only be used in a function that returns `Result`
//~| ERROR expected expression, found `let` statement
while true || let 0 = 0 {} //~ ERROR `let` expressions are not supported here
while (true || let 0 = 0) {} //~ ERROR `let` expressions are not supported here
while true && (true || let 0 = 0) {} //~ ERROR `let` expressions are not supported here
while true || (true && let 0 = 0) {} //~ ERROR `let` expressions are not supported here
while true || let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
while (true || let 0 = 0) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
while true && (true || let 0 = 0) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
while true || (true && let 0 = 0) {}
//~^ ERROR `let` expressions are not supported here
let mut x = true;
while x = let 0 = 0 {} //~ ERROR `let` expressions are not supported here
//~^ ERROR mismatched types
while x = let 0 = 0 {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
while true..(let 0 = 0) {} //~ ERROR `let` expressions are not supported here
//~^ ERROR mismatched types
while ..(let 0 = 0) {} //~ ERROR `let` expressions are not supported here
//~^ ERROR mismatched types
while (let 0 = 0).. {} //~ ERROR `let` expressions are not supported here
//~^ ERROR mismatched types
while true..(let 0 = 0) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
while ..(let 0 = 0) {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
while (let 0 = 0).. {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR mismatched types
//~| ERROR expected expression, found `let` statement
// Binds as `(let ... = true)..true &&/|| false`.
while let Range { start: _, end: _ } = true..true && false {}
@ -216,6 +281,7 @@ fn nested_within_while_expr() {
while let true = let true = true {}
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
}
fn not_error_because_clarified_intent() {
@ -316,15 +382,18 @@ fn inside_const_generic_arguments() {
impl<const B: bool> A<{B}> { const O: u32 = 5; }
if let A::<{
true && let 1 = 1 //~ ERROR `let` expressions are not supported here
true && let 1 = 1
//~^ ERROR `let` expressions are not supported here
}>::O = 5 {}
while let A::<{
true && let 1 = 1 //~ ERROR `let` expressions are not supported here
true && let 1 = 1
//~^ ERROR `let` expressions are not supported here
}>::O = 5 {}
if A::<{
true && let 1 = 1 //~ ERROR `let` expressions are not supported here
true && let 1 = 1
//~^ ERROR `let` expressions are not supported here
}>::O == 5 {}
// In the cases above we have `ExprKind::Block` to help us out.
@ -345,14 +414,18 @@ fn with_parenthesis() {
if (let Some(a) = opt && true) {
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
}
if (let Some(a) = opt) && true {
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
}
if (let Some(a) = opt) && (let Some(b) = a) {
//~^ ERROR `let` expressions are not supported here
//~| ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
}
if let Some(a) = opt && (true && true) {
}
@ -360,13 +433,18 @@ fn with_parenthesis() {
if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
//~^ ERROR `let` expressions are not supported here
//~| ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
}
if (let Some(a) = opt && (let Some(b) = a)) && true {
//~^ ERROR `let` expressions are not supported here
//~| ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
}
if (let Some(a) = opt && (true)) && true {
//~^ ERROR `let` expressions are not supported here
//~| ERROR expected expression, found `let` statement
}
if (true && (true)) && let Some(a) = opt {

View file

@ -19,6 +19,11 @@ fn _if() {
if let Range { start: _, end: _ } = (true..true) && false {}
//~^ ERROR `let` expressions in this position are unstable [E0658]
if let 1 = 1 && let true = { true } && false {
//~^ ERROR `let` expressions in this position are unstable [E0658]
//~| ERROR `let` expressions in this position are unstable [E0658]
}
}
fn _while() {

View file

@ -1,17 +1,17 @@
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:50:20
--> $DIR/feature-gate.rs:55:20
|
LL | #[cfg(FALSE)] (let 0 = 1);
| ^^^
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:40:17
--> $DIR/feature-gate.rs:45:17
|
LL | noop_expr!((let 0 = 1));
| ^^^
error: no rules expected the token `let`
--> $DIR/feature-gate.rs:53:15
--> $DIR/feature-gate.rs:58:15
|
LL | macro_rules! use_expr {
| --------------------- when calling this macro
@ -47,7 +47,25 @@ LL | if let Range { start: _, end: _ } = (true..true) && false {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:27:19
--> $DIR/feature-gate.rs:23:8
|
LL | if let 1 = 1 && let true = { true } && false {
| ^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:23:21
|
LL | if let 1 = 1 && let true = { true } && false {
| ^^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:32:19
|
LL | while true && let 0 = 1 {}
| ^^^^^^^^^
@ -56,7 +74,7 @@ LL | while true && let 0 = 1 {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:30:11
--> $DIR/feature-gate.rs:35:11
|
LL | while let 0 = 1 && true {}
| ^^^^^^^^^
@ -65,7 +83,7 @@ LL | while let 0 = 1 && true {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:33:11
--> $DIR/feature-gate.rs:38:11
|
LL | while let Range { start: _, end: _ } = (true..true) && false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -74,7 +92,7 @@ LL | while let Range { start: _, end: _ } = (true..true) && false {}
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:50:20
--> $DIR/feature-gate.rs:55:20
|
LL | #[cfg(FALSE)] (let 0 = 1);
| ^^^^^^^^^
@ -83,7 +101,7 @@ LL | #[cfg(FALSE)] (let 0 = 1);
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:40:17
--> $DIR/feature-gate.rs:45:17
|
LL | noop_expr!((let 0 = 1));
| ^^^^^^^^^
@ -91,6 +109,6 @@ LL | noop_expr!((let 0 = 1));
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
error: aborting due to 11 previous errors
error: aborting due to 13 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -1,17 +1,45 @@
// check-pass
// known-bug
#![feature(let_chains)]
fn main() {
let _opt = Some(1i32);
#[cfg(FALSE)]
{
let _ = &&let Some(x) = Some(42);
//~^ ERROR expected expression, found `let` statement
}
#[cfg(FALSE)]
{
if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 {
//~^ ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
true
}
}
#[cfg(FALSE)]
{
if let Some(elem) = _opt && {
[1, 2, 3][let _ = ()];
//~^ ERROR expected expression, found `let` statement
true
} {
}
}
#[cfg(FALSE)]
{
if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 {
//~^ ERROR expected expression, found `let` statement
true
}
}
#[cfg(FALSE)]
{
if let a = 1 && {
let x = let y = 1;
//~^ ERROR expected expression, found `let` statement
} {
}
}
}

View file

@ -0,0 +1,38 @@
error: expected expression, found `let` statement
--> $DIR/invalid-let-in-a-valid-let-context.rs:8:19
|
LL | let _ = &&let Some(x) = Some(42);
| ^^^
error: expected expression, found `let` statement
--> $DIR/invalid-let-in-a-valid-let-context.rs:13:47
|
LL | if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 {
| ^^^
error: expected expression, found `let` statement
--> $DIR/invalid-let-in-a-valid-let-context.rs:13:57
|
LL | if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 {
| ^^^
error: expected expression, found `let` statement
--> $DIR/invalid-let-in-a-valid-let-context.rs:23:23
|
LL | [1, 2, 3][let _ = ()];
| ^^^
error: expected expression, found `let` statement
--> $DIR/invalid-let-in-a-valid-let-context.rs:32:47
|
LL | if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 {
| ^^^
error: expected expression, found `let` statement
--> $DIR/invalid-let-in-a-valid-let-context.rs:40:21
|
LL | let x = let y = 1;
| ^^^
error: aborting due to 6 previous errors

View file

@ -0,0 +1,21 @@
macro_rules! num { () => { 1 } }
fn main() {
let x = 1i32;
x.e10; //~ERROR `i32` is a primitive type and therefore doesn't have fields
let y = 1;
y.e10; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields
2u32.e10; //~ERROR `u32` is a primitive type and therefore doesn't have fields
num!().e10; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields
2.e10foo; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields
42._;
//~^ERROR expected identifier, found reserved identifier `_`
//~|ERROR `{integer}` is a primitive type and therefore doesn't have fields
42.a; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields
}

View file

@ -0,0 +1,51 @@
error: expected identifier, found reserved identifier `_`
--> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:16:8
|
LL | 42._;
| ^ expected identifier, found reserved identifier
error[E0610]: `i32` is a primitive type and therefore doesn't have fields
--> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:5:7
|
LL | x.e10;
| ^^^
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
--> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:8:7
|
LL | y.e10;
| ^^^
error[E0610]: `u32` is a primitive type and therefore doesn't have fields
--> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:10:10
|
LL | 2u32.e10;
| ^^^
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
--> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:12:12
|
LL | num!().e10;
| ^^^
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
--> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:14:7
|
LL | 2.e10foo;
| ^^^^^^
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
--> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:16:8
|
LL | 42._;
| ^
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
--> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:20:8
|
LL | 42.a;
| ^
error: aborting due to 8 previous errors
For more information about this error, try `rustc --explain E0610`.

View file

@ -0,0 +1,11 @@
// run-rustfix
fn main() {
2.0e1; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields
2.0E1; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields
2.0f32; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields
2.0f64; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields
2.0e+12; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields
2.0e-12; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields
2.0e1f32; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields
}

View file

@ -0,0 +1,11 @@
// run-rustfix
fn main() {
2.e1; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields
2.E1; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields
2.f32; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields
2.f64; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields
2.e+12; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields
2.e-12; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields
2.e1f32; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields
}

View file

@ -0,0 +1,80 @@
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
--> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:4:7
|
LL | 2.e1;
| ^^
|
help: If the number is meant to be a floating point number, consider adding a `0` after the period
|
LL | 2.0e1;
| +
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
--> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:5:7
|
LL | 2.E1;
| ^^
|
help: If the number is meant to be a floating point number, consider adding a `0` after the period
|
LL | 2.0E1;
| +
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
--> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:6:7
|
LL | 2.f32;
| ^^^
|
help: If the number is meant to be a floating point number, consider adding a `0` after the period
|
LL | 2.0f32;
| +
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
--> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:7:7
|
LL | 2.f64;
| ^^^
|
help: If the number is meant to be a floating point number, consider adding a `0` after the period
|
LL | 2.0f64;
| +
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
--> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:8:7
|
LL | 2.e+12;
| ^
|
help: If the number is meant to be a floating point number, consider adding a `0` after the period
|
LL | 2.0e+12;
| +
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
--> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:9:7
|
LL | 2.e-12;
| ^
|
help: If the number is meant to be a floating point number, consider adding a `0` after the period
|
LL | 2.0e-12;
| +
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
--> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:10:7
|
LL | 2.e1f32;
| ^^^^^
|
help: If the number is meant to be a floating point number, consider adding a `0` after the period
|
LL | 2.0e1f32;
| +
error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0610`.

View file

@ -60,6 +60,8 @@ impl EarlyProps {
pub struct TestProps {
// Lines that should be expected, in order, on standard out
pub error_patterns: Vec<String>,
// Regexes that should be expected, in order, on standard out
pub regex_error_patterns: Vec<String>,
// Extra flags to pass to the compiler
pub compile_flags: Vec<String>,
// Extra flags to pass when the compiled code is run (such as --bench)
@ -163,6 +165,7 @@ pub struct TestProps {
mod directives {
pub const ERROR_PATTERN: &'static str = "error-pattern";
pub const REGEX_ERROR_PATTERN: &'static str = "regex-error-pattern";
pub const COMPILE_FLAGS: &'static str = "compile-flags";
pub const RUN_FLAGS: &'static str = "run-flags";
pub const SHOULD_ICE: &'static str = "should-ice";
@ -200,6 +203,7 @@ impl TestProps {
pub fn new() -> Self {
TestProps {
error_patterns: vec![],
regex_error_patterns: vec![],
compile_flags: vec![],
run_flags: None,
pp_exact: None,
@ -285,6 +289,12 @@ impl TestProps {
&mut self.error_patterns,
|r| r,
);
config.push_name_value_directive(
ln,
REGEX_ERROR_PATTERN,
&mut self.regex_error_patterns,
|r| r,
);
if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) {
self.compile_flags.extend(flags.split_whitespace().map(|s| s.to_owned()));

View file

@ -323,12 +323,13 @@ impl<'test> TestCx<'test> {
let output_to_check = self.get_output(&proc_res);
let expected_errors = errors::load_errors(&self.testpaths.file, self.revision);
if !expected_errors.is_empty() {
if !self.props.error_patterns.is_empty() {
if !self.props.error_patterns.is_empty() || !self.props.regex_error_patterns.is_empty()
{
self.fatal("both error pattern and expected errors specified");
}
self.check_expected_errors(expected_errors, &proc_res);
} else {
self.check_error_patterns(&output_to_check, &proc_res, pm);
self.check_all_error_patterns(&output_to_check, &proc_res, pm);
}
if self.props.should_ice {
match proc_res.status.code() {
@ -363,7 +364,7 @@ impl<'test> TestCx<'test> {
let output_to_check = self.get_output(&proc_res);
self.check_correct_failure_status(&proc_res);
self.check_error_patterns(&output_to_check, &proc_res, pm);
self.check_all_error_patterns(&output_to_check, &proc_res, pm);
}
fn get_output(&self, proc_res: &ProcRes) -> String {
@ -1222,14 +1223,13 @@ impl<'test> TestCx<'test> {
}
}
fn check_error_patterns(
fn check_all_error_patterns(
&self,
output_to_check: &str,
proc_res: &ProcRes,
pm: Option<PassMode>,
) {
debug!("check_error_patterns");
if self.props.error_patterns.is_empty() {
if self.props.error_patterns.is_empty() && self.props.regex_error_patterns.is_empty() {
if pm.is_some() {
// FIXME(#65865)
return;
@ -1243,13 +1243,8 @@ impl<'test> TestCx<'test> {
let mut missing_patterns: Vec<String> = Vec::new();
for pattern in &self.props.error_patterns {
if output_to_check.contains(pattern.trim()) {
debug!("found error pattern {}", pattern);
} else {
missing_patterns.push(pattern.to_string());
}
}
self.check_error_patterns(output_to_check, &mut missing_patterns);
self.check_regex_error_patterns(output_to_check, proc_res, &mut missing_patterns);
if missing_patterns.is_empty() {
return;
@ -1268,6 +1263,44 @@ impl<'test> TestCx<'test> {
}
}
fn check_error_patterns(&self, output_to_check: &str, missing_patterns: &mut Vec<String>) {
debug!("check_error_patterns");
for pattern in &self.props.error_patterns {
if output_to_check.contains(pattern.trim()) {
debug!("found error pattern {}", pattern);
} else {
missing_patterns.push(pattern.to_string());
}
}
}
fn check_regex_error_patterns(
&self,
output_to_check: &str,
proc_res: &ProcRes,
missing_patterns: &mut Vec<String>,
) {
debug!("check_regex_error_patterns");
for pattern in &self.props.regex_error_patterns {
let pattern = pattern.trim();
let re = match Regex::new(pattern) {
Ok(re) => re,
Err(err) => {
self.fatal_proc_rec(
&format!("invalid regex error pattern '{}': {:?}", pattern, err),
proc_res,
);
}
};
if re.is_match(output_to_check) {
debug!("found regex error pattern {}", pattern);
} else {
missing_patterns.push(pattern.to_string());
}
}
}
fn check_no_compiler_crash(&self, proc_res: &ProcRes, should_ice: bool) {
match proc_res.status.code() {
Some(101) if !should_ice => {
@ -1892,7 +1925,9 @@ impl<'test> TestCx<'test> {
// If we are extracting and matching errors in the new
// fashion, then you want JSON mode. Old-skool error
// patterns still match the raw compiler output.
if self.props.error_patterns.is_empty() {
if self.props.error_patterns.is_empty()
&& self.props.regex_error_patterns.is_empty()
{
rustc.args(&["--error-format", "json"]);
rustc.args(&["--json", "future-incompat"]);
}
@ -3268,10 +3303,11 @@ impl<'test> TestCx<'test> {
self.fatal_proc_rec("test run succeeded!", &proc_res);
}
if !self.props.error_patterns.is_empty() {
if !self.props.error_patterns.is_empty() || !self.props.regex_error_patterns.is_empty()
{
// "// error-pattern" comments
let output_to_check = self.get_output(&proc_res);
self.check_error_patterns(&output_to_check, &proc_res, pm);
self.check_all_error_patterns(&output_to_check, &proc_res, pm);
}
}
@ -3285,15 +3321,16 @@ impl<'test> TestCx<'test> {
self.props.error_patterns
);
if !explicit && self.config.compare_mode.is_none() {
let check_patterns =
should_run == WillExecute::No && !self.props.error_patterns.is_empty();
let check_patterns = should_run == WillExecute::No
&& (!self.props.error_patterns.is_empty()
|| !self.props.regex_error_patterns.is_empty());
let check_annotations = !check_patterns || !expected_errors.is_empty();
if check_patterns {
// "// error-pattern" comments
let output_to_check = self.get_output(&proc_res);
self.check_error_patterns(&output_to_check, &proc_res, pm);
self.check_all_error_patterns(&output_to_check, &proc_res, pm);
}
if check_annotations {