Auto merge of #104437 - matthiaskrgr:rollup-n5jdg9v, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - #103439 (Show note where the macro failed to match)
 - #103734 (Adjust stabilization version to 1.65.0 for wasi fds)
 - #104148 (Visit attributes of trait impl items during AST validation)
 - #104241 (Move most of unwind's build script to lib.rs)
 - #104258 (Deduce closure signature from a type alias `impl Trait`'s supertraits)
 - #104296 (Walk types more carefully in `ProhibitOpaqueTypes` visitor)
 - #104309 (Slightly improve error message for invalid identifier)
 - #104316 (Simplify suggestions for errors in generators.)
 - #104339 (Add `rustc_deny_explicit_impl`)

Failed merges:

 - #103484 (Add `rust` to `let_underscore_lock` example)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-11-15 12:35:57 +00:00
commit 6d651a295e
51 changed files with 722 additions and 204 deletions

View File

@ -1051,6 +1051,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl);
});
walk_list!(self, visit_attribute, &item.attrs);
return; // Avoid visiting again.
}
ItemKind::Impl(box Impl {
@ -1168,7 +1169,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
});
walk_list!(self, visit_assoc_item, items, AssocCtxt::Trait);
walk_list!(self, visit_attribute, &item.attrs);
return;
return; // Avoid visiting again
}
ItemKind::Mod(unsafety, ref mod_kind) => {
if let Unsafe::Yes(span) = unsafety {

View File

@ -1,4 +1,5 @@
The `Sized` trait was implemented explicitly.
A built-in trait was implemented explicitly. All implementations of the trait
are provided automatically by the compiler.
Erroneous code example:

View File

@ -384,3 +384,6 @@ parser_fn_ptr_with_generics = function pointer types may not have generic parame
[true] the
*[false] a
} `for` parameter list
parser_invalid_identifier_with_leading_number = expected identifier, found number literal
.label = identifiers cannot start with a number

View File

@ -76,6 +76,7 @@ pub(crate) use ParseResult::*;
use crate::mbe::{macro_rules::Tracker, KleeneOp, TokenTree};
use rustc_ast::token::{self, DocComment, Nonterminal, NonterminalKind, Token};
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lrc;
use rustc_errors::ErrorGuaranteed;
@ -86,6 +87,7 @@ use rustc_span::symbol::MacroRulesNormalizedIdent;
use rustc_span::Span;
use std::borrow::Cow;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::fmt::Display;
/// A unit within a matcher that a `MatcherPos` can refer to. Similar to (and derived from)
/// `mbe::TokenTree`, but designed specifically for fast and easy traversal during matching.
@ -96,7 +98,7 @@ use std::collections::hash_map::Entry::{Occupied, Vacant};
///
/// This means a matcher can be represented by `&[MatcherLoc]`, and traversal mostly involves
/// simply incrementing the current matcher position index by one.
#[derive(Debug)]
#[derive(Debug, PartialEq, Clone)]
pub(crate) enum MatcherLoc {
Token {
token: Token,
@ -129,6 +131,46 @@ pub(crate) enum MatcherLoc {
Eof,
}
impl MatcherLoc {
pub(super) fn span(&self) -> Option<Span> {
match self {
MatcherLoc::Token { token } => Some(token.span),
MatcherLoc::Delimited => None,
MatcherLoc::Sequence { .. } => None,
MatcherLoc::SequenceKleeneOpNoSep { .. } => None,
MatcherLoc::SequenceSep { .. } => None,
MatcherLoc::SequenceKleeneOpAfterSep { .. } => None,
MatcherLoc::MetaVarDecl { span, .. } => Some(*span),
MatcherLoc::Eof => None,
}
}
}
impl Display for MatcherLoc {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
MatcherLoc::Token { token } | MatcherLoc::SequenceSep { separator: token } => {
write!(f, "`{}`", pprust::token_to_string(token))
}
MatcherLoc::MetaVarDecl { bind, kind, .. } => {
write!(f, "meta-variable `${bind}")?;
if let Some(kind) = kind {
write!(f, ":{}", kind)?;
}
write!(f, "`")?;
Ok(())
}
MatcherLoc::Eof => f.write_str("end of macro"),
// These are not printed in the diagnostic
MatcherLoc::Delimited => f.write_str("delimiter"),
MatcherLoc::Sequence { .. } => f.write_str("sequence start"),
MatcherLoc::SequenceKleeneOpNoSep { .. } => f.write_str("sequence end"),
MatcherLoc::SequenceKleeneOpAfterSep { .. } => f.write_str("sequence end"),
}
}
}
pub(super) fn compute_locs(matcher: &[TokenTree]) -> Vec<MatcherLoc> {
fn inner(
tts: &[TokenTree],
@ -398,6 +440,10 @@ impl TtParser {
}
}
pub(super) fn has_no_remaining_items_for_step(&self) -> bool {
self.cur_mps.is_empty()
}
/// Process the matcher positions of `cur_mps` until it is empty. In the process, this will
/// produce more mps in `next_mps` and `bb_mps`.
///

View File

@ -337,7 +337,7 @@ fn expand_macro<'cx>(
return result;
}
let Some((token, label)) = tracker.best_failure else {
let Some((token, label, remaining_matcher)) = tracker.best_failure else {
return tracker.result.expect("must have encountered Error or ErrorReported");
};
@ -351,6 +351,12 @@ fn expand_macro<'cx>(
annotate_doc_comment(&mut err, sess.source_map(), span);
if let Some(span) = remaining_matcher.span() {
err.span_note(span, format!("while trying to match {remaining_matcher}"));
} else {
err.note(format!("while trying to match {remaining_matcher}"));
}
// Check whether there's a missing comma in this macro call, like `println!("{}" a);`
if let Some((arg, comma_span)) = arg.add_comma() {
for lhs in lhses {
@ -379,17 +385,22 @@ fn expand_macro<'cx>(
}
/// The tracker used for the slow error path that collects useful info for diagnostics.
struct CollectTrackerAndEmitter<'a, 'cx> {
struct CollectTrackerAndEmitter<'a, 'cx, 'matcher> {
cx: &'a mut ExtCtxt<'cx>,
remaining_matcher: Option<&'matcher MatcherLoc>,
/// Which arm's failure should we report? (the one furthest along)
best_failure: Option<(Token, &'static str)>,
best_failure: Option<(Token, &'static str, MatcherLoc)>,
root_span: Span,
result: Option<Box<dyn MacResult + 'cx>>,
}
impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx> {
fn before_match_loc(&mut self, _parser: &TtParser, _matcher: &'matcher MatcherLoc) {
// Empty for now.
impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, 'matcher> {
fn before_match_loc(&mut self, parser: &TtParser, matcher: &'matcher MatcherLoc) {
if self.remaining_matcher.is_none()
|| (parser.has_no_remaining_items_for_step() && *matcher != MatcherLoc::Eof)
{
self.remaining_matcher = Some(matcher);
}
}
fn after_arm(&mut self, result: &NamedParseResult) {
@ -398,8 +409,16 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx>
unreachable!("should not collect detailed info for successful macro match");
}
Failure(token, msg) => match self.best_failure {
Some((ref best_token, _)) if best_token.span.lo() >= token.span.lo() => {}
_ => self.best_failure = Some((token.clone(), msg)),
Some((ref best_token, _, _)) if best_token.span.lo() >= token.span.lo() => {}
_ => {
self.best_failure = Some((
token.clone(),
msg,
self.remaining_matcher
.expect("must have collected matcher already")
.clone(),
))
}
},
Error(err_sp, msg) => {
let span = err_sp.substitute_dummy(self.root_span);
@ -415,9 +434,9 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx>
}
}
impl<'a, 'cx> CollectTrackerAndEmitter<'a, 'cx> {
impl<'a, 'cx> CollectTrackerAndEmitter<'a, 'cx, '_> {
fn new(cx: &'a mut ExtCtxt<'cx>, root_span: Span) -> Self {
Self { cx, best_failure: None, root_span, result: None }
Self { cx, remaining_matcher: None, best_failure: None, root_span, result: None }
}
}

View File

@ -691,6 +691,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: true,
"#[rustc_allow_incoherent_impl] has to be added to all impl items of an incoherent inherent impl."
),
rustc_attr!(
rustc_deny_explicit_impl, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: false,
"#[rustc_deny_explicit_impl] enforces that a trait can have no user-provided impls"
),
rustc_attr!(
rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word), ErrorFollowing,
"#[rustc_has_incoherent_inherent_impls] allows the addition of incoherent inherent impls for \

View File

@ -5,10 +5,11 @@
// done by the orphan and overlap modules. Then we build up various
// mappings. That mapping code resides here.
use rustc_errors::struct_span_err;
use rustc_errors::{error_code, struct_span_err};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
use rustc_span::sym;
use rustc_trait_selection::traits;
mod builtin;
@ -39,61 +40,26 @@ fn enforce_trait_manually_implementable(
impl_def_id: LocalDefId,
trait_def_id: DefId,
) {
let did = Some(trait_def_id);
let li = tcx.lang_items();
let impl_header_span = tcx.def_span(impl_def_id);
// Disallow *all* explicit impls of `Pointee`, `DiscriminantKind`, `Sized` and `Unsize` for now.
if did == li.pointee_trait() {
struct_span_err!(
// Disallow *all* explicit impls of traits marked `#[rustc_deny_explicit_impl]`
if tcx.has_attr(trait_def_id, sym::rustc_deny_explicit_impl) {
let trait_name = tcx.item_name(trait_def_id);
let mut err = struct_span_err!(
tcx.sess,
impl_header_span,
E0322,
"explicit impls for the `Pointee` trait are not permitted"
)
.span_label(impl_header_span, "impl of `Pointee` not allowed")
.emit();
return;
}
"explicit impls for the `{trait_name}` trait are not permitted"
);
err.span_label(impl_header_span, format!("impl of `{trait_name}` not allowed"));
if did == li.discriminant_kind_trait() {
struct_span_err!(
tcx.sess,
impl_header_span,
E0322,
"explicit impls for the `DiscriminantKind` trait are not permitted"
)
.span_label(impl_header_span, "impl of `DiscriminantKind` not allowed")
.emit();
return;
}
// Maintain explicit error code for `Unsize`, since it has a useful
// explanation about using `CoerceUnsized` instead.
if Some(trait_def_id) == tcx.lang_items().unsize_trait() {
err.code(error_code!(E0328));
}
if did == li.sized_trait() {
struct_span_err!(
tcx.sess,
impl_header_span,
E0322,
"explicit impls for the `Sized` trait are not permitted"
)
.span_label(impl_header_span, "impl of `Sized` not allowed")
.emit();
return;
}
if did == li.unsize_trait() {
struct_span_err!(
tcx.sess,
impl_header_span,
E0328,
"explicit impls for the `Unsize` trait are not permitted"
)
.span_label(impl_header_span, "impl of `Unsize` not allowed")
.emit();
return;
}
if tcx.features().unboxed_closures {
// the feature gate allows all Fn traits
err.emit();
return;
}

View File

@ -173,34 +173,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected_ty: Ty<'tcx>,
) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
match *expected_ty.kind() {
ty::Opaque(def_id, substs) => {
let bounds = self.tcx.bound_explicit_item_bounds(def_id);
let sig =
bounds.subst_iter_copied(self.tcx, substs).find_map(|(pred, span)| match pred
.kind()
.skip_binder()
{
ty::PredicateKind::Projection(proj_predicate) => self
.deduce_sig_from_projection(
Some(span),
pred.kind().rebind(proj_predicate),
),
_ => None,
});
let kind = bounds
.0
.iter()
.filter_map(|(pred, _)| match pred.kind().skip_binder() {
ty::PredicateKind::Trait(tp) => {
self.tcx.fn_trait_kind_from_lang_item(tp.def_id())
}
_ => None,
})
.fold(None, |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur))));
trace!(?sig, ?kind);
(sig, kind)
}
ty::Opaque(def_id, substs) => self.deduce_signature_from_predicates(
self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs),
),
ty::Dynamic(ref object_type, ..) => {
let sig = object_type.projection_bounds().find_map(|pb| {
let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self);
@ -211,7 +186,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.and_then(|did| self.tcx.fn_trait_kind_from_lang_item(did));
(sig, kind)
}
ty::Infer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),
ty::Infer(ty::TyVar(vid)) => self.deduce_signature_from_predicates(
self.obligations_for_self_ty(vid).map(|obl| (obl.predicate, obl.cause.span)),
),
ty::FnPtr(sig) => {
let expected_sig = ExpectedSig { cause_span: None, sig };
(Some(expected_sig), Some(ty::ClosureKind::Fn))
@ -220,19 +197,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
fn deduce_expectations_from_obligations(
fn deduce_signature_from_predicates(
&self,
expected_vid: ty::TyVid,
predicates: impl DoubleEndedIterator<Item = (ty::Predicate<'tcx>, Span)>,
) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
let mut expected_sig = None;
let mut expected_kind = None;
for obligation in traits::elaborate_obligations(
for obligation in traits::elaborate_predicates_with_span(
self.tcx,
// Reverse the obligations here, since `elaborate_*` uses a stack,
// and we want to keep inference generally in the same order of
// the registered obligations.
self.obligations_for_self_ty(expected_vid).rev().collect(),
predicates.rev(),
) {
debug!(?obligation.predicate);
let bound_predicate = obligation.predicate.kind();

View File

@ -1195,35 +1195,30 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
}
fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool {
struct ProhibitOpaqueTypes<'a, 'tcx> {
cx: &'a LateContext<'tcx>,
}
impl<'a, 'tcx> ty::visit::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> {
struct ProhibitOpaqueTypes;
impl<'tcx> ty::visit::TypeVisitor<'tcx> for ProhibitOpaqueTypes {
type BreakTy = Ty<'tcx>;
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match ty.kind() {
ty::Opaque(..) => ControlFlow::Break(ty),
// Consider opaque types within projections FFI-safe if they do not normalize
// to more opaque types.
ty::Projection(..) => {
let ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, ty);
if !ty.has_opaque_types() {
return ControlFlow::CONTINUE;
}
// If `ty` is an opaque type directly then `super_visit_with` won't invoke
// this function again.
if ty.has_opaque_types() {
self.visit_ty(ty)
} else {
ControlFlow::CONTINUE
}
}
_ => ty.super_visit_with(self),
if let ty::Opaque(..) = ty.kind() {
ControlFlow::Break(ty)
} else {
ty.super_visit_with(self)
}
}
}
if let Some(ty) = ty.visit_with(&mut ProhibitOpaqueTypes { cx: self.cx }).break_value() {
if let Some(ty) = self
.cx
.tcx
.normalize_erasing_regions(self.cx.param_env, ty)
.visit_with(&mut ProhibitOpaqueTypes)
.break_value()
{
self.emit_ffi_unsafe_type_lint(ty, sp, fluent::lint_improper_ctypes_opaque, None);
true
} else {

View File

@ -6,7 +6,6 @@ use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts};
use crate::ty::visit::{TypeVisitable, TypeVisitor};
use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
use rustc_data_structures::captures::Captures;
use rustc_data_structures::intern::{Interned, WithStableHash};
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
@ -19,7 +18,7 @@ use std::fmt;
use std::marker::PhantomData;
use std::mem;
use std::num::NonZeroUsize;
use std::ops::ControlFlow;
use std::ops::{ControlFlow, Deref};
use std::slice;
/// An entity in the Rust type system, which can be one of
@ -562,25 +561,86 @@ impl<T, U> EarlyBinder<(T, U)> {
}
}
impl<'tcx, 's, T: IntoIterator<Item = I>, I: TypeFoldable<'tcx>> EarlyBinder<T> {
impl<'tcx, 's, I: IntoIterator> EarlyBinder<I>
where
I::Item: TypeFoldable<'tcx>,
{
pub fn subst_iter(
self,
tcx: TyCtxt<'tcx>,
substs: &'s [GenericArg<'tcx>],
) -> impl Iterator<Item = I> + Captures<'s> + Captures<'tcx> {
self.0.into_iter().map(move |t| EarlyBinder(t).subst(tcx, substs))
) -> SubstIter<'s, 'tcx, I> {
SubstIter { it: self.0.into_iter(), tcx, substs }
}
}
impl<'tcx, 's, 'a, T: IntoIterator<Item = &'a I>, I: Copy + TypeFoldable<'tcx> + 'a>
EarlyBinder<T>
pub struct SubstIter<'s, 'tcx, I: IntoIterator> {
it: I::IntoIter,
tcx: TyCtxt<'tcx>,
substs: &'s [GenericArg<'tcx>],
}
impl<'tcx, I: IntoIterator> Iterator for SubstIter<'_, 'tcx, I>
where
I::Item: TypeFoldable<'tcx>,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
Some(EarlyBinder(self.it.next()?).subst(self.tcx, self.substs))
}
}
impl<'tcx, I: IntoIterator> DoubleEndedIterator for SubstIter<'_, 'tcx, I>
where
I::IntoIter: DoubleEndedIterator,
I::Item: TypeFoldable<'tcx>,
{
fn next_back(&mut self) -> Option<Self::Item> {
Some(EarlyBinder(self.it.next_back()?).subst(self.tcx, self.substs))
}
}
impl<'tcx, 's, I: IntoIterator> EarlyBinder<I>
where
I::Item: Deref,
<I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>,
{
pub fn subst_iter_copied(
self,
tcx: TyCtxt<'tcx>,
substs: &'s [GenericArg<'tcx>],
) -> impl Iterator<Item = I> + Captures<'s> + Captures<'tcx> + Captures<'a> {
self.0.into_iter().map(move |t| EarlyBinder(*t).subst(tcx, substs))
) -> SubstIterCopied<'s, 'tcx, I> {
SubstIterCopied { it: self.0.into_iter(), tcx, substs }
}
}
pub struct SubstIterCopied<'a, 'tcx, I: IntoIterator> {
it: I::IntoIter,
tcx: TyCtxt<'tcx>,
substs: &'a [GenericArg<'tcx>],
}
impl<'tcx, I: IntoIterator> Iterator for SubstIterCopied<'_, 'tcx, I>
where
I::Item: Deref,
<I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>,
{
type Item = <I::Item as Deref>::Target;
fn next(&mut self) -> Option<Self::Item> {
Some(EarlyBinder(*self.it.next()?).subst(self.tcx, self.substs))
}
}
impl<'tcx, I: IntoIterator> DoubleEndedIterator for SubstIterCopied<'_, 'tcx, I>
where
I::IntoIter: DoubleEndedIterator,
I::Item: Deref,
<I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>,
{
fn next_back(&mut self) -> Option<Self::Item> {
Some(EarlyBinder(*self.it.next_back()?).subst(self.tcx, self.substs))
}
}

View File

@ -1205,6 +1205,14 @@ pub(crate) struct SelfParamNotFirst {
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(parser_invalid_identifier_with_leading_number)]
pub(crate) struct InvalidIdentiferStartsWithNumber {
#[primary_span]
#[label]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(parser_const_generic_without_braces)]
pub(crate) struct ConstGenericWithoutBraces {

View File

@ -10,8 +10,8 @@ use super::{
use crate::errors::{
AssignmentElseNotAllowed, CompoundAssignmentExpressionInLet, ConstLetMutuallyExclusive,
DocCommentDoesNotDocumentAnything, ExpectedStatementAfterOuterAttr, InvalidCurlyInLetElse,
InvalidExpressionInLetElse, InvalidVariableDeclaration, InvalidVariableDeclarationSub,
WrapExpressionInParentheses,
InvalidExpressionInLetElse, InvalidIdentiferStartsWithNumber, InvalidVariableDeclaration,
InvalidVariableDeclarationSub, WrapExpressionInParentheses,
};
use crate::maybe_whole;
@ -264,6 +264,7 @@ impl<'a> Parser<'a> {
self.bump();
}
self.report_invalid_identifier_error()?;
let (pat, colon) = self.parse_pat_before_ty(None, RecoverComma::Yes, "`let` bindings")?;
let (err, ty) = if colon {
@ -355,6 +356,17 @@ impl<'a> Parser<'a> {
Ok(P(ast::Local { ty, pat, kind, id: DUMMY_NODE_ID, span: lo.to(hi), attrs, tokens: None }))
}
/// report error for `let 1x = 123`
pub fn report_invalid_identifier_error(&mut self) -> PResult<'a, ()> {
if let token::Literal(lit) = self.token.uninterpolate().kind &&
let Err(_) = rustc_ast::Lit::from_token(&self.token) &&
(lit.kind == token::LitKind::Integer || lit.kind == token::LitKind::Float) &&
self.look_ahead(1, |t| matches!(t.kind, token::Eq) || matches!(t.kind, token::Colon ) ) {
return Err(self.sess.create_err(InvalidIdentiferStartsWithNumber { span: self.token.span }));
}
Ok(())
}
fn check_let_else_init_bool_expr(&self, init: &ast::Expr) {
if let ast::ExprKind::Binary(op, ..) = init.kind {
if op.node.lazy() {

View File

@ -1210,6 +1210,7 @@ symbols! {
rustc_deallocator,
rustc_def_path,
rustc_default_body_unstable,
rustc_deny_explicit_impl,
rustc_diagnostic_item,
rustc_diagnostic_macros,
rustc_dirty,

View File

@ -44,7 +44,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
#[derive(Debug)]
pub enum GeneratorInteriorOrUpvar {
// span of interior type
Interior(Span),
Interior(Span, Option<(Option<Span>, Span, Option<hir::HirId>, Option<Span>)>),
// span of upvar
Upvar(Span),
}
@ -283,7 +283,6 @@ pub trait TypeErrCtxtExt<'tcx> {
&self,
err: &mut Diagnostic,
interior_or_upvar_span: GeneratorInteriorOrUpvar,
interior_extra_info: Option<(Option<Span>, Span, Option<hir::HirId>, Option<Span>)>,
is_async: bool,
outer_generator: Option<DefId>,
trait_pred: ty::TraitPredicate<'tcx>,
@ -2003,17 +2002,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
.as_local()
.and_then(|def_id| hir.maybe_body_owned_by(def_id))
.map(|body_id| hir.body(body_id));
let is_async = match generator_did.as_local() {
Some(_) => generator_body
.and_then(|body| body.generator_kind())
.map(|generator_kind| matches!(generator_kind, hir::GeneratorKind::Async(..)))
.unwrap_or(false),
None => self
.tcx
.generator_kind(generator_did)
.map(|generator_kind| matches!(generator_kind, hir::GeneratorKind::Async(..)))
.unwrap_or(false),
};
let is_async = self
.tcx
.generator_kind(generator_did)
.map(|generator_kind| matches!(generator_kind, hir::GeneratorKind::Async(..)))
.unwrap_or(false);
let mut visitor = AwaitsVisitor::default();
if let Some(body) = generator_body {
visitor.visit_body(body);
@ -2043,61 +2036,60 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
eq
};
let mut interior_or_upvar_span = None;
let mut interior_extra_info = None;
// Get the typeck results from the infcx if the generator is the function we are currently
// type-checking; otherwise, get them by performing a query. This is needed to avoid
// cycles. If we can't use resolved types because the generator comes from another crate,
// we still provide a targeted error but without all the relevant spans.
let generator_data: Option<GeneratorData<'tcx, '_>> = match &self.typeck_results {
Some(t) if t.hir_owner.to_def_id() == generator_did_root => {
Some(GeneratorData::Local(&t))
}
let generator_data = match &self.typeck_results {
Some(t) if t.hir_owner.to_def_id() == generator_did_root => GeneratorData::Local(&t),
_ if generator_did.is_local() => {
Some(GeneratorData::Local(self.tcx.typeck(generator_did.expect_local())))
GeneratorData::Local(self.tcx.typeck(generator_did.expect_local()))
}
_ => self
.tcx
.generator_diagnostic_data(generator_did)
.as_ref()
.map(|generator_diag_data| GeneratorData::Foreign(generator_diag_data)),
_ if let Some(generator_diag_data) = self.tcx.generator_diagnostic_data(generator_did) => {
GeneratorData::Foreign(generator_diag_data)
}
_ => return false,
};
if let Some(generator_data) = generator_data.as_ref() {
interior_or_upvar_span =
generator_data.try_get_upvar_span(&self, generator_did, ty_matches);
let mut interior_or_upvar_span = None;
// The generator interior types share the same binders
if let Some(cause) =
generator_data.get_generator_interior_types().skip_binder().iter().find(
|ty::GeneratorInteriorTypeCause { ty, .. }| {
ty_matches(generator_data.get_generator_interior_types().rebind(*ty))
},
)
{
let from_awaited_ty = generator_data.get_from_await_ty(visitor, hir, ty_matches);
let ty::GeneratorInteriorTypeCause { span, scope_span, yield_span, expr, .. } =
cause;
let from_awaited_ty = generator_data.get_from_await_ty(visitor, hir, ty_matches);
debug!(?from_awaited_ty);
interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(*span));
interior_extra_info = Some((*scope_span, *yield_span, *expr, from_awaited_ty));
}
// The generator interior types share the same binders
if let Some(cause) =
generator_data.get_generator_interior_types().skip_binder().iter().find(
|ty::GeneratorInteriorTypeCause { ty, .. }| {
ty_matches(generator_data.get_generator_interior_types().rebind(*ty))
},
)
{
let ty::GeneratorInteriorTypeCause { span, scope_span, yield_span, expr, .. } = cause;
if interior_or_upvar_span.is_none() && generator_data.is_foreign() {
interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(span));
}
interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(
*span,
Some((*scope_span, *yield_span, *expr, from_awaited_ty)),
));
}
if interior_or_upvar_span.is_none() {
interior_or_upvar_span =
generator_data.try_get_upvar_span(&self, generator_did, ty_matches);
}
if interior_or_upvar_span.is_none() && generator_data.is_foreign() {
interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(span, None));
}
debug!(?interior_or_upvar_span);
if let Some(interior_or_upvar_span) = interior_or_upvar_span {
let typeck_results = generator_data.and_then(|generator_data| match generator_data {
let typeck_results = match generator_data {
GeneratorData::Local(typeck_results) => Some(typeck_results),
GeneratorData::Foreign(_) => None,
});
};
self.note_obligation_cause_for_async_await(
err,
interior_or_upvar_span,
interior_extra_info,
is_async,
outer_generator,
trait_ref,
@ -2119,7 +2111,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
&self,
err: &mut Diagnostic,
interior_or_upvar_span: GeneratorInteriorOrUpvar,
interior_extra_info: Option<(Option<Span>, Span, Option<hir::HirId>, Option<Span>)>,
is_async: bool,
outer_generator: Option<DefId>,
trait_pred: ty::TraitPredicate<'tcx>,
@ -2241,7 +2232,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
};
match interior_or_upvar_span {
GeneratorInteriorOrUpvar::Interior(interior_span) => {
GeneratorInteriorOrUpvar::Interior(interior_span, interior_extra_info) => {
if let Some((scope_span, yield_span, expr, from_awaited_ty)) = interior_extra_info {
if let Some(await_span) = from_awaited_ty {
// The type causing this obligation is one being awaited at await_span.

View File

@ -96,6 +96,7 @@ unsafe impl<T: Sync + ?Sized> Send for &T {}
)]
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
#[rustc_specialization_trait]
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
pub trait Sized {
// Empty.
}
@ -127,6 +128,7 @@ pub trait Sized {
/// [nomicon-coerce]: ../../nomicon/coercions.html
#[unstable(feature = "unsize", issue = "27732")]
#[lang = "unsize"]
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
pub trait Unsize<T: ?Sized> {
// Empty.
}
@ -693,6 +695,7 @@ impl<T: ?Sized> StructuralEq for PhantomData<T> {}
reason = "this trait is unlikely to ever be stabilized, use `mem::discriminant` instead"
)]
#[lang = "discriminant_kind"]
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
pub trait DiscriminantKind {
/// The type of the discriminant, which must satisfy the trait
/// bounds required by `mem::Discriminant`.
@ -793,6 +796,7 @@ impl<T: ?Sized> Unpin for *mut T {}
#[lang = "destruct"]
#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
#[const_trait]
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
pub trait Destruct {}
/// A marker for tuple types.
@ -802,6 +806,7 @@ pub trait Destruct {}
#[unstable(feature = "tuple_trait", issue = "none")]
#[lang = "tuple_trait"]
#[rustc_on_unimplemented(message = "`{Self}` is not a tuple")]
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
pub trait Tuple {}
/// Implementations of `Copy` for primitive types.

View File

@ -50,6 +50,7 @@ use crate::hash::{Hash, Hasher};
///
/// [`to_raw_parts`]: *const::to_raw_parts
#[lang = "pointee_trait"]
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
pub trait Pointee {
/// The type for metadata in pointers and references to `Self`.
#[lang = "metadata_type"]

View File

@ -1,6 +1,6 @@
//! WASI-specific extensions to general I/O primitives.
#![stable(feature = "io_safety", since = "1.63.0")]
#![stable(feature = "io_safety_wasi", since = "1.65.0")]
#[stable(feature = "io_safety", since = "1.63.0")]
#[stable(feature = "io_safety_wasi", since = "1.65.0")]
pub use crate::os::fd::*;

View File

@ -21,29 +21,5 @@ fn main() {
if has_unwind {
println!("cargo:rustc-cfg=feature=\"system-llvm-libunwind\"");
}
} else if target.contains("freebsd") {
println!("cargo:rustc-link-lib=gcc_s");
} else if target.contains("netbsd") {
println!("cargo:rustc-link-lib=gcc_s");
} else if target.contains("openbsd") {
if target.contains("sparc64") {
println!("cargo:rustc-link-lib=gcc");
} else {
println!("cargo:rustc-link-lib=c++abi");
}
} else if target.contains("solaris") {
println!("cargo:rustc-link-lib=gcc_s");
} else if target.contains("illumos") {
println!("cargo:rustc-link-lib=gcc_s");
} else if target.contains("dragonfly") {
println!("cargo:rustc-link-lib=gcc_pic");
} else if target.ends_with("pc-windows-gnu") {
// This is handled in the target spec with late_link_args_[static|dynamic]
} else if target.contains("uwp-windows-gnu") {
println!("cargo:rustc-link-lib=unwind");
} else if target.contains("haiku") {
println!("cargo:rustc-link-lib=gcc_s");
} else if target.contains("redox") {
// redox is handled in lib.rs
}
}

View File

@ -103,3 +103,27 @@ extern "C" {}
#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
#[link(name = "unwind", kind = "static", modifiers = "-bundle")]
extern "C" {}
#[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
#[link(name = "gcc_s")]
extern "C" {}
#[cfg(all(target_os = "openbsd", target_arch = "sparc64"))]
#[link(name = "gcc")]
extern "C" {}
#[cfg(all(target_os = "openbsd", not(target_arch = "sparc64")))]
#[link(name = "c++abi")]
extern "C" {}
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
#[link(name = "gcc_s")]
extern "C" {}
#[cfg(target_os = "dragonfly")]
#[link(name = "gcc_pic")]
extern "C" {}
#[cfg(target_os = "haiku")]
#[link(name = "gcc_s")]
extern "C" {}

View File

@ -3,6 +3,8 @@ error: no rules expected the token `,`
|
LL | vec![,];
| ^ no rules expected this token in macro call
|
= note: while trying to match end of macro
error: aborting due to previous error

View File

@ -53,6 +53,12 @@ LL | macro_rules! gimme_a_const {
...
LL | let _fail = Example::<gimme_a_const!()>;
| ^^^^^^^^^^^^^^^^ missing tokens in macro arguments
|
note: while trying to match meta-variable `$rusty:ident`
--> $DIR/macro-fail.rs:28:8
|
LL | ($rusty: ident) => {{ let $rusty = 3; *&$rusty }}
| ^^^^^^^^^^^^^
error[E0747]: type provided when a constant was expected
--> $DIR/macro-fail.rs:14:33

View File

@ -3,12 +3,24 @@ error: no rules expected the token `r#async`
|
LL | r#async = consumes_async!(r#async);
| ^^^^^^^ no rules expected this token in macro call
|
note: while trying to match `async`
--> $DIR/auxiliary/edition-kw-macro-2015.rs:17:6
|
LL | (async) => (1)
| ^^^^^
error: no rules expected the token `async`
--> $DIR/edition-keywords-2015-2015-parsing.rs:17:35
|
LL | r#async = consumes_async_raw!(async);
| ^^^^^ no rules expected this token in macro call
|
note: while trying to match `r#async`
--> $DIR/auxiliary/edition-kw-macro-2015.rs:22:6
|
LL | (r#async) => (1)
| ^^^^^^^
error: aborting due to 2 previous errors

View File

@ -3,12 +3,24 @@ error: no rules expected the token `r#async`
|
LL | r#async = consumes_async!(r#async);
| ^^^^^^^ no rules expected this token in macro call
|
note: while trying to match `async`
--> $DIR/auxiliary/edition-kw-macro-2018.rs:17:6
|
LL | (async) => (1)
| ^^^^^
error: no rules expected the token `async`
--> $DIR/edition-keywords-2015-2018-parsing.rs:17:35
|
LL | r#async = consumes_async_raw!(async);
| ^^^^^ no rules expected this token in macro call
|
note: while trying to match `r#async`
--> $DIR/auxiliary/edition-kw-macro-2018.rs:22:6
|
LL | (r#async) => (1)
| ^^^^^^^
error: aborting due to 2 previous errors

View File

@ -25,12 +25,24 @@ error: no rules expected the token `r#async`
|
LL | r#async = consumes_async!(r#async);
| ^^^^^^^ no rules expected this token in macro call
|
note: while trying to match `async`
--> $DIR/auxiliary/edition-kw-macro-2015.rs:17:6
|
LL | (async) => (1)
| ^^^^^
error: no rules expected the token `async`
--> $DIR/edition-keywords-2018-2015-parsing.rs:21:35
|
LL | r#async = consumes_async_raw!(async);
| ^^^^^ no rules expected this token in macro call
|
note: while trying to match `r#async`
--> $DIR/auxiliary/edition-kw-macro-2015.rs:22:6
|
LL | (r#async) => (1)
| ^^^^^^^
error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||`
--> $DIR/auxiliary/edition-kw-macro-2015.rs:27:23

View File

@ -25,12 +25,24 @@ error: no rules expected the token `r#async`
|
LL | r#async = consumes_async!(r#async);
| ^^^^^^^ no rules expected this token in macro call
|
note: while trying to match `async`
--> $DIR/auxiliary/edition-kw-macro-2018.rs:17:6
|
LL | (async) => (1)
| ^^^^^
error: no rules expected the token `async`
--> $DIR/edition-keywords-2018-2018-parsing.rs:21:35
|
LL | r#async = consumes_async_raw!(async);
| ^^^^^ no rules expected this token in macro call
|
note: while trying to match `r#async`
--> $DIR/auxiliary/edition-kw-macro-2018.rs:22:6
|
LL | (r#async) => (1)
| ^^^^^^^
error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||`
--> $DIR/auxiliary/edition-kw-macro-2018.rs:27:23

View File

@ -6,6 +6,12 @@ LL | macro_rules! one_arg_macro {
...
LL | one_arg_macro!(/**/);
| ^^^^^^^^^^^^^^^^^^^^ missing tokens in macro arguments
|
note: while trying to match meta-variable `$fmt:expr`
--> $DIR/empty-comment.rs:6:6
|
LL | ($fmt:expr) => (print!(concat!($fmt, "\n")));
| ^^^^^^^^^
error: aborting due to previous error

View File

@ -3,6 +3,8 @@ error: no rules expected the token `@`
|
LL | panic!(@);
| ^ no rules expected this token in macro call
|
= note: while trying to match end of macro
error: aborting due to previous error

View File

@ -0,0 +1,15 @@
// check-pass
#![feature(type_alias_impl_trait)]
trait SuperExpectation: Fn(i32) {}
impl<T: Fn(i32)> SuperExpectation for T {}
type Foo = impl SuperExpectation;
fn main() {
let _: Foo = |x| {
let _ = x.to_string();
};
}

View File

@ -6,6 +6,12 @@ LL | macro_rules! one_arg_macro {
...
LL | one_arg_macro!();
| ^^^^^^^^^^^^^^^^ missing tokens in macro arguments
|
note: while trying to match meta-variable `$fmt:expr`
--> $DIR/issue-7970a.rs:2:6
|
LL | ($fmt:expr) => (print!(concat!($fmt, "\n")));
| ^^^^^^^^^
error: aborting due to previous error

View File

@ -0,0 +1,41 @@
#![feature(type_alias_impl_trait)]
#![allow(unused)]
#![deny(improper_ctypes)]
pub trait TraitA {
type Assoc;
}
impl TraitA for u32 {
type Assoc = u32;
}
pub trait TraitB {
type Assoc;
}
impl<T> TraitB for T
where
T: TraitA,
{
type Assoc = <T as TraitA>::Assoc;
}
type AliasA = impl TraitA<Assoc = u32>;
type AliasB = impl TraitB;
fn use_of_a() -> AliasA {
3
}
fn use_of_b() -> AliasB {
3
}
extern "C" {
fn lint_me() -> <AliasB as TraitB>::Assoc;
//~^ ERROR `extern` block uses type `AliasB`, which is not FFI-safe
}
fn main() {}

View File

@ -0,0 +1,15 @@
error: `extern` block uses type `AliasB`, which is not FFI-safe
--> $DIR/opaque-ty-ffi-normalization-cycle.rs:37:21
|
LL | fn lint_me() -> <AliasB as TraitB>::Assoc;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
= note: opaque types have no C equivalent
note: the lint level is defined here
--> $DIR/opaque-ty-ffi-normalization-cycle.rs:3:9
|
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
error: aborting due to previous error

View File

@ -17,6 +17,8 @@ LL | assert!(true, "whatever" blah);
| -^^^^ no rules expected this token in macro call
| |
| help: missing comma here
|
= note: while trying to match sequence start
error: unexpected string literal
--> $DIR/assert-trailing-junk.rs:18:18
@ -33,6 +35,8 @@ LL | assert!(true "whatever" blah);
| -^^^^ no rules expected this token in macro call
| |
| help: missing comma here
|
= note: while trying to match sequence start
error: macro requires an expression as an argument
--> $DIR/assert-trailing-junk.rs:22:5

View File

@ -17,6 +17,8 @@ LL | assert!(true, "whatever" blah);
| -^^^^ no rules expected this token in macro call
| |
| help: missing comma here
|
= note: while trying to match sequence start
error: unexpected string literal
--> $DIR/assert-trailing-junk.rs:18:18
@ -33,6 +35,8 @@ LL | assert!(true "whatever" blah);
| -^^^^ no rules expected this token in macro call
| |
| help: missing comma here
|
= note: while trying to match sequence start
error: macro requires an expression as an argument
--> $DIR/assert-trailing-junk.rs:22:5

View File

@ -12,6 +12,8 @@ LL | macro_rules! foo {
...
LL | foo!(a?);
| ^ no rules expected this token in macro call
|
= note: while trying to match sequence end
error: no rules expected the token `?`
--> $DIR/macro-at-most-once-rep-2015.rs:26:11
@ -21,6 +23,8 @@ LL | macro_rules! foo {
...
LL | foo!(a?a);
| ^ no rules expected this token in macro call
|
= note: while trying to match sequence end
error: no rules expected the token `?`
--> $DIR/macro-at-most-once-rep-2015.rs:27:11
@ -30,6 +34,8 @@ LL | macro_rules! foo {
...
LL | foo!(a?a?a);
| ^ no rules expected this token in macro call
|
= note: while trying to match sequence end
error: unexpected end of macro invocation
--> $DIR/macro-at-most-once-rep-2015.rs:29:5
@ -39,6 +45,12 @@ LL | macro_rules! barplus {
...
LL | barplus!();
| ^^^^^^^^^^ missing tokens in macro arguments
|
note: while trying to match `+`
--> $DIR/macro-at-most-once-rep-2015.rs:15:11
|
LL | ($(a)?+) => {}; // ok. matches "a+" and "+"
| ^
error: unexpected end of macro invocation
--> $DIR/macro-at-most-once-rep-2015.rs:30:15
@ -48,6 +60,12 @@ LL | macro_rules! barplus {
...
LL | barplus!(a);
| ^ missing tokens in macro arguments
|
note: while trying to match `+`
--> $DIR/macro-at-most-once-rep-2015.rs:15:11
|
LL | ($(a)?+) => {}; // ok. matches "a+" and "+"
| ^
error: no rules expected the token `?`
--> $DIR/macro-at-most-once-rep-2015.rs:31:15
@ -57,6 +75,12 @@ LL | macro_rules! barplus {
...
LL | barplus!(a?);
| ^ no rules expected this token in macro call
|
note: while trying to match `+`
--> $DIR/macro-at-most-once-rep-2015.rs:15:11
|
LL | ($(a)?+) => {}; // ok. matches "a+" and "+"
| ^
error: no rules expected the token `?`
--> $DIR/macro-at-most-once-rep-2015.rs:32:15
@ -66,6 +90,12 @@ LL | macro_rules! barplus {
...
LL | barplus!(a?a);
| ^ no rules expected this token in macro call
|
note: while trying to match `+`
--> $DIR/macro-at-most-once-rep-2015.rs:15:11
|
LL | ($(a)?+) => {}; // ok. matches "a+" and "+"
| ^
error: unexpected end of macro invocation
--> $DIR/macro-at-most-once-rep-2015.rs:36:5
@ -75,6 +105,12 @@ LL | macro_rules! barstar {
...
LL | barstar!();
| ^^^^^^^^^^ missing tokens in macro arguments
|
note: while trying to match `*`
--> $DIR/macro-at-most-once-rep-2015.rs:19:11
|
LL | ($(a)?*) => {}; // ok. matches "a*" and "*"
| ^
error: unexpected end of macro invocation
--> $DIR/macro-at-most-once-rep-2015.rs:37:15
@ -84,6 +120,12 @@ LL | macro_rules! barstar {
...
LL | barstar!(a);
| ^ missing tokens in macro arguments
|
note: while trying to match `*`
--> $DIR/macro-at-most-once-rep-2015.rs:19:11
|
LL | ($(a)?*) => {}; // ok. matches "a*" and "*"
| ^
error: no rules expected the token `?`
--> $DIR/macro-at-most-once-rep-2015.rs:38:15
@ -93,6 +135,12 @@ LL | macro_rules! barstar {
...
LL | barstar!(a?);
| ^ no rules expected this token in macro call
|
note: while trying to match `*`
--> $DIR/macro-at-most-once-rep-2015.rs:19:11
|
LL | ($(a)?*) => {}; // ok. matches "a*" and "*"
| ^
error: no rules expected the token `?`
--> $DIR/macro-at-most-once-rep-2015.rs:39:15
@ -102,6 +150,12 @@ LL | macro_rules! barstar {
...
LL | barstar!(a?a);
| ^ no rules expected this token in macro call
|
note: while trying to match `*`
--> $DIR/macro-at-most-once-rep-2015.rs:19:11
|
LL | ($(a)?*) => {}; // ok. matches "a*" and "*"
| ^
error: aborting due to 12 previous errors

View File

@ -12,6 +12,8 @@ LL | macro_rules! foo {
...
LL | foo!(a?);
| ^ no rules expected this token in macro call
|
= note: while trying to match sequence end
error: no rules expected the token `?`
--> $DIR/macro-at-most-once-rep-2018.rs:26:11
@ -21,6 +23,8 @@ LL | macro_rules! foo {
...
LL | foo!(a?a);
| ^ no rules expected this token in macro call
|
= note: while trying to match sequence end
error: no rules expected the token `?`
--> $DIR/macro-at-most-once-rep-2018.rs:27:11
@ -30,6 +34,8 @@ LL | macro_rules! foo {
...
LL | foo!(a?a?a);
| ^ no rules expected this token in macro call
|
= note: while trying to match sequence end
error: unexpected end of macro invocation
--> $DIR/macro-at-most-once-rep-2018.rs:29:5
@ -39,6 +45,12 @@ LL | macro_rules! barplus {
...
LL | barplus!();
| ^^^^^^^^^^ missing tokens in macro arguments
|
note: while trying to match `+`
--> $DIR/macro-at-most-once-rep-2018.rs:15:11
|
LL | ($(a)?+) => {}; // ok. matches "a+" and "+"
| ^
error: unexpected end of macro invocation
--> $DIR/macro-at-most-once-rep-2018.rs:30:15
@ -48,6 +60,12 @@ LL | macro_rules! barplus {
...
LL | barplus!(a);
| ^ missing tokens in macro arguments
|
note: while trying to match `+`
--> $DIR/macro-at-most-once-rep-2018.rs:15:11
|
LL | ($(a)?+) => {}; // ok. matches "a+" and "+"
| ^
error: no rules expected the token `?`
--> $DIR/macro-at-most-once-rep-2018.rs:31:15
@ -57,6 +75,12 @@ LL | macro_rules! barplus {
...
LL | barplus!(a?);
| ^ no rules expected this token in macro call
|
note: while trying to match `+`
--> $DIR/macro-at-most-once-rep-2018.rs:15:11
|
LL | ($(a)?+) => {}; // ok. matches "a+" and "+"
| ^
error: no rules expected the token `?`
--> $DIR/macro-at-most-once-rep-2018.rs:32:15
@ -66,6 +90,12 @@ LL | macro_rules! barplus {
...
LL | barplus!(a?a);
| ^ no rules expected this token in macro call
|
note: while trying to match `+`
--> $DIR/macro-at-most-once-rep-2018.rs:15:11
|
LL | ($(a)?+) => {}; // ok. matches "a+" and "+"
| ^
error: unexpected end of macro invocation
--> $DIR/macro-at-most-once-rep-2018.rs:36:5
@ -75,6 +105,12 @@ LL | macro_rules! barstar {
...
LL | barstar!();
| ^^^^^^^^^^ missing tokens in macro arguments
|
note: while trying to match `*`
--> $DIR/macro-at-most-once-rep-2018.rs:19:11
|
LL | ($(a)?*) => {}; // ok. matches "a*" and "*"
| ^
error: unexpected end of macro invocation
--> $DIR/macro-at-most-once-rep-2018.rs:37:15
@ -84,6 +120,12 @@ LL | macro_rules! barstar {
...
LL | barstar!(a);
| ^ missing tokens in macro arguments
|
note: while trying to match `*`
--> $DIR/macro-at-most-once-rep-2018.rs:19:11
|
LL | ($(a)?*) => {}; // ok. matches "a*" and "*"
| ^
error: no rules expected the token `?`
--> $DIR/macro-at-most-once-rep-2018.rs:38:15
@ -93,6 +135,12 @@ LL | macro_rules! barstar {
...
LL | barstar!(a?);
| ^ no rules expected this token in macro call
|
note: while trying to match `*`
--> $DIR/macro-at-most-once-rep-2018.rs:19:11
|
LL | ($(a)?*) => {}; // ok. matches "a*" and "*"
| ^
error: no rules expected the token `?`
--> $DIR/macro-at-most-once-rep-2018.rs:39:15
@ -102,6 +150,12 @@ LL | macro_rules! barstar {
...
LL | barstar!(a?a);
| ^ no rules expected this token in macro call
|
note: while trying to match `*`
--> $DIR/macro-at-most-once-rep-2018.rs:19:11
|
LL | ($(a)?*) => {}; // ok. matches "a*" and "*"
| ^
error: aborting due to 12 previous errors

View File

@ -6,6 +6,12 @@ LL | macro_rules! m { ($x:lifetime) => { } }
...
LL | m!(a);
| ^ no rules expected this token in macro call
|
note: while trying to match meta-variable `$x:lifetime`
--> $DIR/macro-non-lifetime.rs:3:19
|
LL | macro_rules! m { ($x:lifetime) => { } }
| ^^^^^^^^^^^
error: aborting due to previous error

View File

@ -14,6 +14,12 @@ LL | foo!(a b);
| -^ no rules expected this token in macro call
| |
| help: missing comma here
|
note: while trying to match meta-variable `$a:ident`
--> $DIR/missing-comma.rs:2:6
|
LL | ($a:ident) => ();
| ^^^^^^^^
error: no rules expected the token `e`
--> $DIR/missing-comma.rs:23:21
@ -25,6 +31,12 @@ LL | foo!(a, b, c, d e);
| -^ no rules expected this token in macro call
| |
| help: missing comma here
|
note: while trying to match meta-variable `$d:ident`
--> $DIR/missing-comma.rs:5:36
|
LL | ($a:ident, $b:ident, $c:ident, $d:ident) => ();
| ^^^^^^^^
error: no rules expected the token `d`
--> $DIR/missing-comma.rs:25:18
@ -36,6 +48,12 @@ LL | foo!(a, b, c d, e);
| -^ no rules expected this token in macro call
| |
| help: missing comma here
|
note: while trying to match meta-variable `$c:ident`
--> $DIR/missing-comma.rs:4:26
|
LL | ($a:ident, $b:ident, $c:ident) => ();
| ^^^^^^^^
error: no rules expected the token `d`
--> $DIR/missing-comma.rs:27:18
@ -45,6 +63,12 @@ LL | macro_rules! foo {
...
LL | foo!(a, b, c d e);
| ^ no rules expected this token in macro call
|
note: while trying to match meta-variable `$c:ident`
--> $DIR/missing-comma.rs:4:26
|
LL | ($a:ident, $b:ident, $c:ident) => ();
| ^^^^^^^^
error: unexpected end of macro invocation
--> $DIR/missing-comma.rs:29:23
@ -54,6 +78,12 @@ LL | macro_rules! bar {
...
LL | bar!(Level::Error, );
| ^ missing tokens in macro arguments
|
note: while trying to match meta-variable `$arg:tt`
--> $DIR/missing-comma.rs:10:19
|
LL | ($lvl:expr, $($arg:tt)+) => {}
| ^^^^^^^
error: no rules expected the token `,`
--> $DIR/missing-comma.rs:32:38
@ -63,6 +93,12 @@ LL | macro_rules! check {
...
LL | check!(<str as Debug>::fmt, "fmt",);
| ^ no rules expected this token in macro call
|
note: while trying to match meta-variable `$expected:expr`
--> $DIR/missing-comma.rs:14:14
|
LL | ($ty:ty, $expected:expr) => {};
| ^^^^^^^^^^^^^^
error: aborting due to 7 previous errors

View File

@ -10,6 +10,14 @@ LL | n!(a $nt_item b);
LL | complex_nonterminal!(enum E {});
| ------------------------------- in this macro invocation
|
note: while trying to match `enum E {}`
--> $DIR/nonterminal-matching.rs:15:15
|
LL | macro n(a $nt_item b) {
| ^^^^^^^^
...
LL | complex_nonterminal!(enum E {});
| ------------------------------- in this macro invocation
= note: this error originates in the macro `complex_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -10,6 +10,7 @@ LL | my_faulty_macro!(bcd);
LL | my_faulty_macro!();
| ------------------ in this macro invocation
|
= note: while trying to match end of macro
= note: this error originates in the macro `my_faulty_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
note: trace_macro

View File

@ -0,0 +1,8 @@
#![feature(rustc_attrs)]
trait Foo {}
#[rustc_on_unimplemented] //~ ERROR malformed `rustc_on_unimplemented` attribute input
impl Foo for u32 {}
fn main() {}

View File

@ -0,0 +1,15 @@
error: malformed `rustc_on_unimplemented` attribute input
--> $DIR/issue-104140.rs:5:1
|
LL | #[rustc_on_unimplemented]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: the following are the possible correct uses
|
LL | #[rustc_on_unimplemented = "message"]
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LL | #[rustc_on_unimplemented(/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...")]
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error

View File

@ -6,6 +6,12 @@ LL | macro_rules! accept_pat {
...
LL | accept_pat!(p | q);
| ^ no rules expected this token in macro call
|
note: while trying to match meta-variable `$p:pat`
--> $DIR/or-patterns-syntactic-fail-2018.rs:9:6
|
LL | ($p:pat) => {};
| ^^^^^^
error: no rules expected the token `|`
--> $DIR/or-patterns-syntactic-fail-2018.rs:13:13
@ -15,6 +21,12 @@ LL | macro_rules! accept_pat {
...
LL | accept_pat!(|p| q);
| ^ no rules expected this token in macro call
|
note: while trying to match meta-variable `$p:pat`
--> $DIR/or-patterns-syntactic-fail-2018.rs:9:6
|
LL | ($p:pat) => {};
| ^^^^^^
error: aborting due to 2 previous errors

View File

@ -0,0 +1,26 @@
fn test() {
if let 123 = 123 { println!("yes"); }
}
fn test_2() {
let 1x = 123;
//~^ ERROR expected identifier, found number literal
}
fn test_3() {
let 2x: i32 = 123;
//~^ ERROR expected identifier, found number literal
}
fn test_4() {
if let 2e1 = 123 {
//~^ ERROR mismatched types
}
}
fn test_5() {
let 23name = 123;
//~^ ERROR expected identifier, found number literal
}
fn main() {}

View File

@ -0,0 +1,29 @@
error: expected identifier, found number literal
--> $DIR/issue-104088.rs:6:9
|
LL | let 1x = 123;
| ^^ identifiers cannot start with a number
error: expected identifier, found number literal
--> $DIR/issue-104088.rs:11:9
|
LL | let 2x: i32 = 123;
| ^^ identifiers cannot start with a number
error: expected identifier, found number literal
--> $DIR/issue-104088.rs:22:9
|
LL | let 23name = 123;
| ^^^^^^ identifiers cannot start with a number
error[E0308]: mismatched types
--> $DIR/issue-104088.rs:16:12
|
LL | if let 2e1 = 123 {
| ^^^ --- this expression has type `{integer}`
| |
| expected integer, found floating-point number
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0308`.

View File

@ -9,6 +9,12 @@ LL | //! Inner
| |
| no rules expected this token in macro call
| inner doc comments expand to `#![doc = "..."]`, which is what this macro attempted to match
|
note: while trying to match `[`
--> $DIR/macro-doc-comments-1.rs:2:7
|
LL | (#[$outer:meta]) => ()
| ^
error: aborting due to previous error

View File

@ -9,6 +9,12 @@ LL | /// Outer
| |
| no rules expected this token in macro call
| outer doc comments expand to `#[doc = "..."]`, which is what this macro attempted to match
|
note: while trying to match `!`
--> $DIR/macro-doc-comments-2.rs:2:7
|
LL | (#![$inner:meta]) => ()
| ^
error: aborting due to previous error

View File

@ -72,6 +72,12 @@ LL | macro_rules! use_expr {
...
LL | use_expr!(let 0 = 1);
| ^^^ no rules expected this token in macro call
|
note: while trying to match meta-variable `$e:expr`
--> $DIR/feature-gate.rs:61:10
|
LL | ($e:expr) => {
| ^^^^^^^
error[E0658]: `if let` guards are experimental
--> $DIR/feature-gate.rs:7:12

View File

@ -18,6 +18,12 @@ LL | macro_rules! use_expr {
...
LL | use_expr!(let 0 = 1);
| ^^^ no rules expected this token in macro call
|
note: while trying to match meta-variable `$e:expr`
--> $DIR/feature-gate.rs:50:10
|
LL | ($e:expr) => {
| ^^^^^^^
error[E0658]: `let` expressions in this position are unstable
--> $DIR/feature-gate.rs:14:16

View File

@ -6,6 +6,12 @@ LL | macro_rules! identity {
...
LL | let identity!(_) = 10;
| ^ no rules expected this token in macro call
|
note: while trying to match meta-variable `$i:ident`
--> $DIR/underscore-ident-matcher.rs:2:6
|
LL | ($i: ident) => (
| ^^^^^^^^^
error: aborting due to previous error