Auto merge of #150115 - JonathanBrouwer:rollup-3gqipmq, r=JonathanBrouwer
Rollup of 4 pull requests Successful merges: - rust-lang/rust#149922 (Tidying up tests/ui/issues 14 tests [5/N]) - rust-lang/rust#150095 (Port `#[rustc_no_implicit_autorefs]`, `#[rustc_lint_opt_ty]`, and `#[rustc_lint_query_instability]` attributes to be parsed) - rust-lang/rust#150099 ([rustdoc] Fix invalid handling of field followed by negated macro call) - rust-lang/rust#150113 (Update tracking issue for PinCoerceUnsized) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
686f9cefc3
44 changed files with 235 additions and 156 deletions
|
|
@ -27,6 +27,21 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcNeverReturnsNullPointerParser {
|
|||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNeverReturnsNullPointer;
|
||||
}
|
||||
pub(crate) struct RustcNoImplicitAutorefsParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcNoImplicitAutorefsParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_no_implicit_autorefs];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Fn),
|
||||
Allow(Target::Method(MethodKind::Inherent)),
|
||||
Allow(Target::Method(MethodKind::Trait { body: false })),
|
||||
Allow(Target::Method(MethodKind::Trait { body: true })),
|
||||
Allow(Target::Method(MethodKind::TraitImpl)),
|
||||
]);
|
||||
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitAutorefs;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcLayoutScalarValidRangeStartParser;
|
||||
|
||||
|
|
@ -102,6 +117,30 @@ impl<S: Stage> SingleAttributeParser<S> for RustcLegacyConstGenericsParser {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RustcLintOptTyParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcLintOptTyParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_lint_opt_ty];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintOptTy;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcLintQueryInstabilityParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcLintQueryInstabilityParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_lint_query_instability];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Fn),
|
||||
Allow(Target::Method(MethodKind::Inherent)),
|
||||
Allow(Target::Method(MethodKind::Trait { body: false })),
|
||||
Allow(Target::Method(MethodKind::Trait { body: true })),
|
||||
Allow(Target::Method(MethodKind::TraitImpl)),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintQueryInstability;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcObjectLifetimeDefaultParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcObjectLifetimeDefaultParser {
|
||||
|
|
|
|||
|
|
@ -61,7 +61,8 @@ use crate::attributes::prototype::CustomMirParser;
|
|||
use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser};
|
||||
use crate::attributes::rustc_internal::{
|
||||
RustcLayoutScalarValidRangeEndParser, RustcLayoutScalarValidRangeStartParser,
|
||||
RustcLegacyConstGenericsParser, RustcMainParser, RustcNeverReturnsNullPointerParser,
|
||||
RustcLegacyConstGenericsParser, RustcLintOptTyParser, RustcLintQueryInstabilityParser,
|
||||
RustcMainParser, RustcNeverReturnsNullPointerParser, RustcNoImplicitAutorefsParser,
|
||||
RustcObjectLifetimeDefaultParser, RustcScalableVectorParser,
|
||||
RustcSimdMonomorphizeLaneLimitParser,
|
||||
};
|
||||
|
|
@ -255,8 +256,11 @@ attribute_parsers!(
|
|||
Single<WithoutArgs<ProcMacroParser>>,
|
||||
Single<WithoutArgs<PubTransparentParser>>,
|
||||
Single<WithoutArgs<RustcCoherenceIsCoreParser>>,
|
||||
Single<WithoutArgs<RustcLintOptTyParser>>,
|
||||
Single<WithoutArgs<RustcLintQueryInstabilityParser>>,
|
||||
Single<WithoutArgs<RustcMainParser>>,
|
||||
Single<WithoutArgs<RustcNeverReturnsNullPointerParser>>,
|
||||
Single<WithoutArgs<RustcNoImplicitAutorefsParser>>,
|
||||
Single<WithoutArgs<RustcPassIndirectlyInNonRusticAbisParser>>,
|
||||
Single<WithoutArgs<RustcShouldNotBeCalledOnConstItems>>,
|
||||
Single<WithoutArgs<SpecializationTraitParser>>,
|
||||
|
|
|
|||
|
|
@ -931,12 +931,21 @@ pub enum AttributeKind {
|
|||
/// Represents `#[rustc_legacy_const_generics]`
|
||||
RustcLegacyConstGenerics { fn_indexes: ThinVec<(usize, Span)>, attr_span: Span },
|
||||
|
||||
/// Represents `#[rustc_lint_opt_ty]`
|
||||
RustcLintOptTy,
|
||||
|
||||
/// Represents `#[rustc_lint_query_instability]`
|
||||
RustcLintQueryInstability,
|
||||
|
||||
/// Represents `#[rustc_main]`.
|
||||
RustcMain,
|
||||
|
||||
/// Represents `#[rustc_never_returns_null_ptr]`
|
||||
RustcNeverReturnsNullPointer,
|
||||
|
||||
/// Represents `#[rustc_no_implicit_autorefs]`
|
||||
RustcNoImplicitAutorefs,
|
||||
|
||||
/// Represents `#[rustc_object_lifetime_default]`.
|
||||
RustcObjectLifetimeDefault,
|
||||
|
||||
|
|
|
|||
|
|
@ -94,8 +94,11 @@ impl AttributeKind {
|
|||
RustcLayoutScalarValidRangeEnd(..) => Yes,
|
||||
RustcLayoutScalarValidRangeStart(..) => Yes,
|
||||
RustcLegacyConstGenerics { .. } => Yes,
|
||||
RustcLintOptTy => Yes,
|
||||
RustcLintQueryInstability => Yes,
|
||||
RustcMain => No,
|
||||
RustcNeverReturnsNullPointer => Yes,
|
||||
RustcNoImplicitAutorefs => Yes,
|
||||
RustcObjectLifetimeDefault => No,
|
||||
RustcPassIndirectlyInNonRusticAbis(..) => No,
|
||||
RustcScalableVector { .. } => Yes,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use rustc_ast::{BorrowKind, UnOp};
|
||||
use rustc_hir::{Expr, ExprKind, Mutability};
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::{Expr, ExprKind, Mutability, find_attr};
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, OverloadedDeref};
|
||||
use rustc_session::{declare_lint, declare_lint_pass};
|
||||
use rustc_span::sym;
|
||||
|
||||
use crate::lints::{
|
||||
ImplicitUnsafeAutorefsDiag, ImplicitUnsafeAutorefsMethodNote, ImplicitUnsafeAutorefsOrigin,
|
||||
|
|
@ -106,7 +106,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitAutorefs {
|
|||
ExprKind::MethodCall(..) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
|
||||
_ => None,
|
||||
}
|
||||
&& method_did.map(|did| cx.tcx.has_attr(did, sym::rustc_no_implicit_autorefs)).unwrap_or(true)
|
||||
&& method_did.map(|did| find_attr!(cx.tcx.get_all_attrs(did), AttributeKind::RustcNoImplicitAutorefs)).unwrap_or(true)
|
||||
{
|
||||
cx.emit_span_lint(
|
||||
DANGEROUS_IMPLICIT_AUTOREFS,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
//! Some lints that are only useful in the compiler or crates that use compiler internals, such as
|
||||
//! Clippy.
|
||||
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{Expr, ExprKind, HirId};
|
||||
use rustc_hir::{Expr, ExprKind, HirId, find_attr};
|
||||
use rustc_middle::ty::{self, GenericArgsRef, PredicatePolarity, Ty};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
||||
|
|
@ -90,7 +91,7 @@ impl<'tcx> LateLintPass<'tcx> for QueryStability {
|
|||
ty::Instance::try_resolve(cx.tcx, cx.typing_env(), callee_def_id, generic_args)
|
||||
{
|
||||
let def_id = instance.def_id();
|
||||
if cx.tcx.has_attr(def_id, sym::rustc_lint_query_instability) {
|
||||
if find_attr!(cx.tcx.get_all_attrs(def_id), AttributeKind::RustcLintQueryInstability) {
|
||||
cx.emit_span_lint(
|
||||
POTENTIAL_QUERY_INSTABILITY,
|
||||
span,
|
||||
|
|
@ -150,7 +151,10 @@ fn has_unstable_into_iter_predicate<'tcx>(
|
|||
};
|
||||
// Does the input type's `IntoIterator` implementation have the
|
||||
// `rustc_lint_query_instability` attribute on its `into_iter` method?
|
||||
if cx.tcx.has_attr(instance.def_id(), sym::rustc_lint_query_instability) {
|
||||
if find_attr!(
|
||||
cx.tcx.get_all_attrs(instance.def_id()),
|
||||
AttributeKind::RustcLintQueryInstability
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -658,7 +662,7 @@ impl LateLintPass<'_> for BadOptAccess {
|
|||
let Some(adt_def) = cx.typeck_results().expr_ty(base).ty_adt_def() else { return };
|
||||
// Skip types without `#[rustc_lint_opt_ty]` - only so that the rest of the lint can be
|
||||
// avoided.
|
||||
if !cx.tcx.has_attr(adt_def.did(), sym::rustc_lint_opt_ty) {
|
||||
if !find_attr!(cx.tcx.get_all_attrs(adt_def.did()), AttributeKind::RustcLintOptTy) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -477,10 +477,6 @@ passes_rustc_lint_opt_deny_field_access =
|
|||
`#[rustc_lint_opt_deny_field_access]` should be applied to a field
|
||||
.label = not a field
|
||||
|
||||
passes_rustc_lint_opt_ty =
|
||||
`#[rustc_lint_opt_ty]` should be applied to a struct
|
||||
.label = not a struct
|
||||
|
||||
passes_rustc_pub_transparent =
|
||||
attribute should be applied to `#[repr(transparent)]` types
|
||||
.label = not a `#[repr(transparent)]` type
|
||||
|
|
|
|||
|
|
@ -255,8 +255,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| AttributeKind::MacroUse { .. }
|
||||
| AttributeKind::MacroEscape( .. )
|
||||
| AttributeKind::NoLink
|
||||
| AttributeKind::RustcNoImplicitAutorefs
|
||||
| AttributeKind::RustcLayoutScalarValidRangeStart(..)
|
||||
| AttributeKind::RustcLayoutScalarValidRangeEnd(..)
|
||||
| AttributeKind::RustcLintOptTy
|
||||
| AttributeKind::RustcLintQueryInstability
|
||||
| AttributeKind::RustcNeverReturnsNullPointer
|
||||
| AttributeKind::RustcScalableVector { .. }
|
||||
| AttributeKind::RustcSimdMonomorphizeLaneLimit(..)
|
||||
|
|
@ -305,19 +308,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
self.check_diagnostic_on_const(attr.span(), hir_id, target, item)
|
||||
}
|
||||
[sym::thread_local, ..] => self.check_thread_local(attr, span, target),
|
||||
[sym::rustc_no_implicit_autorefs, ..] => {
|
||||
self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target)
|
||||
}
|
||||
[sym::rustc_lint_query_instability, ..] => {
|
||||
self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target)
|
||||
}
|
||||
[sym::rustc_lint_untracked_query_information, ..] => {
|
||||
self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target)
|
||||
}
|
||||
[sym::rustc_lint_diagnostics, ..] => {
|
||||
self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target)
|
||||
}
|
||||
[sym::rustc_lint_opt_ty, ..] => self.check_rustc_lint_opt_ty(attr, span, target),
|
||||
[sym::rustc_lint_opt_deny_field_access, ..] => {
|
||||
self.check_rustc_lint_opt_deny_field_access(attr, span, target)
|
||||
}
|
||||
|
|
@ -1255,16 +1251,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Checks that the `#[rustc_lint_opt_ty]` attribute is only applied to a struct.
|
||||
fn check_rustc_lint_opt_ty(&self, attr: &Attribute, span: Span, target: Target) {
|
||||
match target {
|
||||
Target::Struct => {}
|
||||
_ => {
|
||||
self.dcx().emit_err(errors::RustcLintOptTy { attr_span: attr.span(), span });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks that the `#[rustc_lint_opt_deny_field_access]` attribute is only applied to a field.
|
||||
fn check_rustc_lint_opt_deny_field_access(&self, attr: &Attribute, span: Span, target: Target) {
|
||||
match target {
|
||||
|
|
|
|||
|
|
@ -412,15 +412,6 @@ pub(crate) struct UnusedMultiple {
|
|||
pub name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_rustc_lint_opt_ty)]
|
||||
pub(crate) struct RustcLintOptTy {
|
||||
#[primary_span]
|
||||
pub attr_span: Span,
|
||||
#[label]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_rustc_lint_opt_deny_field_access)]
|
||||
pub(crate) struct RustcLintOptDenyFieldAccess {
|
||||
|
|
|
|||
|
|
@ -2253,7 +2253,7 @@ impl<Args: Tuple, F: AsyncFn<Args> + ?Sized, A: Allocator> AsyncFn<Args> for Box
|
|||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> for Box<T, A> {}
|
||||
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
|
||||
unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Box<T, A> {}
|
||||
|
||||
// It is quite crucial that we only allow the `Global` allocator here.
|
||||
|
|
|
|||
|
|
@ -2417,14 +2417,14 @@ impl<T: ?Sized, A: Allocator> Deref for Rc<T, A> {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
|
||||
unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Rc<T, A> {}
|
||||
|
||||
//#[unstable(feature = "unique_rc_arc", issue = "112566")]
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
|
||||
unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for UniqueRc<T, A> {}
|
||||
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
|
||||
unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Weak<T, A> {}
|
||||
|
||||
#[unstable(feature = "deref_pure_trait", issue = "87121")]
|
||||
|
|
|
|||
|
|
@ -2423,10 +2423,10 @@ impl<T: ?Sized, A: Allocator> Deref for Arc<T, A> {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
|
||||
unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Arc<T, A> {}
|
||||
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
|
||||
unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Weak<T, A> {}
|
||||
|
||||
#[unstable(feature = "deref_pure_trait", issue = "87121")]
|
||||
|
|
@ -4852,7 +4852,7 @@ impl<T: ?Sized, A: Allocator> Deref for UniqueArc<T, A> {
|
|||
}
|
||||
|
||||
// #[unstable(feature = "unique_rc_arc", issue = "112566")]
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
|
||||
unsafe impl<T: ?Sized> PinCoerceUnsized for UniqueArc<T> {}
|
||||
|
||||
#[unstable(feature = "unique_rc_arc", issue = "112566")]
|
||||
|
|
|
|||
|
|
@ -2696,20 +2696,20 @@ fn assert_coerce_unsized(
|
|||
let _: RefCell<&dyn Send> = d;
|
||||
}
|
||||
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
|
||||
unsafe impl<T: ?Sized> PinCoerceUnsized for UnsafeCell<T> {}
|
||||
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
|
||||
unsafe impl<T: ?Sized> PinCoerceUnsized for SyncUnsafeCell<T> {}
|
||||
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
|
||||
unsafe impl<T: ?Sized> PinCoerceUnsized for Cell<T> {}
|
||||
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
|
||||
unsafe impl<T: ?Sized> PinCoerceUnsized for RefCell<T> {}
|
||||
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
|
||||
unsafe impl<'b, T: ?Sized> PinCoerceUnsized for Ref<'b, T> {}
|
||||
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
|
||||
unsafe impl<'b, T: ?Sized> PinCoerceUnsized for RefMut<'b, T> {}
|
||||
|
|
|
|||
|
|
@ -1825,7 +1825,7 @@ where
|
|||
{
|
||||
}
|
||||
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
|
||||
/// Trait that indicates that this is a pointer or a wrapper for one, where
|
||||
/// unsizing can be performed on the pointee when it is pinned.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ impl<T: PointeeSized, U: PointeeSized> CoerceUnsized<Unique<U>> for Unique<T> wh
|
|||
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||
impl<T: PointeeSized, U: PointeeSized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> {}
|
||||
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
|
||||
unsafe impl<T: PointeeSized> PinCoerceUnsized for Unique<T> {}
|
||||
|
||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||
|
|
|
|||
|
|
@ -773,7 +773,7 @@ where
|
|||
#[unstable(feature = "sgx_platform", issue = "56975")]
|
||||
impl<T: CoerceUnsized<U>, U> CoerceUnsized<UserRef<U>> for UserRef<T> {}
|
||||
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
|
||||
unsafe impl<T: ?Sized> PinCoerceUnsized for UserRef<T> {}
|
||||
|
||||
#[unstable(feature = "sgx_platform", issue = "56975")]
|
||||
|
|
|
|||
|
|
@ -832,6 +832,20 @@ impl<'a> PeekIter<'a> {
|
|||
.copied()
|
||||
}
|
||||
|
||||
fn peek_next_if<F: Fn((TokenKind, &'a str)) -> bool>(
|
||||
&mut self,
|
||||
f: F,
|
||||
) -> Option<(TokenKind, &'a str)> {
|
||||
let next = self.peek_next()?;
|
||||
if f(next) {
|
||||
Some(next)
|
||||
} else {
|
||||
// We go one step back.
|
||||
self.peek_pos -= 1;
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn stop_peeking(&mut self) {
|
||||
self.peek_pos = 0;
|
||||
}
|
||||
|
|
@ -903,18 +917,17 @@ fn classify<'src>(
|
|||
}
|
||||
}
|
||||
|
||||
if let Some((TokenKind::Colon | TokenKind::Ident, _)) = classifier.tokens.peek() {
|
||||
let tokens = classifier.get_full_ident_path();
|
||||
for &(token, start, end) in &tokens {
|
||||
let text = &classifier.src[start..end];
|
||||
classifier.advance(token, text, sink, start as u32);
|
||||
classifier.byte_pos += text.len() as u32;
|
||||
}
|
||||
if !tokens.is_empty() {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if let Some((token, text, before)) = classifier.next() {
|
||||
if let Some((TokenKind::Colon | TokenKind::Ident, _)) = classifier.tokens.peek()
|
||||
&& let Some(nb_items) = classifier.get_full_ident_path()
|
||||
{
|
||||
let start = classifier.byte_pos as usize;
|
||||
let len: usize = iter::from_fn(|| classifier.next())
|
||||
.take(nb_items)
|
||||
.map(|(_, text, _)| text.len())
|
||||
.sum();
|
||||
let text = &classifier.src[start..start + len];
|
||||
classifier.advance(TokenKind::Ident, text, sink, start as u32);
|
||||
} else if let Some((token, text, before)) = classifier.next() {
|
||||
classifier.advance(token, text, sink, before);
|
||||
} else {
|
||||
break;
|
||||
|
|
@ -957,47 +970,47 @@ impl<'src> Classifier<'src> {
|
|||
}
|
||||
|
||||
/// Concatenate colons and idents as one when possible.
|
||||
fn get_full_ident_path(&mut self) -> Vec<(TokenKind, usize, usize)> {
|
||||
let start = self.byte_pos as usize;
|
||||
let mut pos = start;
|
||||
fn get_full_ident_path(&mut self) -> Option<usize> {
|
||||
let mut has_ident = false;
|
||||
let mut nb_items = 0;
|
||||
|
||||
loop {
|
||||
let ret = loop {
|
||||
let mut nb = 0;
|
||||
while let Some((TokenKind::Colon, _)) = self.tokens.peek() {
|
||||
self.tokens.next();
|
||||
while self.tokens.peek_next_if(|(token, _)| token == TokenKind::Colon).is_some() {
|
||||
nb += 1;
|
||||
nb_items += 1;
|
||||
}
|
||||
// Ident path can start with "::" but if we already have content in the ident path,
|
||||
// the "::" is mandatory.
|
||||
if has_ident && nb == 0 {
|
||||
return vec![(TokenKind::Ident, start, pos)];
|
||||
break Some(nb_items);
|
||||
} else if nb != 0 && nb != 2 {
|
||||
if has_ident {
|
||||
return vec![(TokenKind::Ident, start, pos), (TokenKind::Colon, pos, pos + nb)];
|
||||
// Following `;` will be handled on its own.
|
||||
break Some(nb_items - 1);
|
||||
} else {
|
||||
return vec![(TokenKind::Colon, start, pos + nb)];
|
||||
break None;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((TokenKind::Ident, text)) = self.tokens.peek()
|
||||
if let Some((TokenKind::Ident, text)) =
|
||||
self.tokens.peek_next_if(|(token, _)| token == TokenKind::Ident)
|
||||
&& let symbol = Symbol::intern(text)
|
||||
&& (symbol.is_path_segment_keyword() || !is_keyword(symbol))
|
||||
{
|
||||
// We only "add" the colon if there is an ident behind.
|
||||
pos += text.len() + nb;
|
||||
has_ident = true;
|
||||
self.tokens.next();
|
||||
nb_items += 1;
|
||||
} else if nb > 0 && has_ident {
|
||||
return vec![(TokenKind::Ident, start, pos), (TokenKind::Colon, pos, pos + nb)];
|
||||
} else if nb > 0 {
|
||||
return vec![(TokenKind::Colon, start, start + nb)];
|
||||
// Following `;` will be handled on its own.
|
||||
break Some(nb_items - 1);
|
||||
} else if has_ident {
|
||||
return vec![(TokenKind::Ident, start, pos)];
|
||||
break Some(nb_items);
|
||||
} else {
|
||||
return Vec::new();
|
||||
break None;
|
||||
}
|
||||
}
|
||||
};
|
||||
self.tokens.stop_peeking();
|
||||
ret
|
||||
}
|
||||
|
||||
/// Wraps the tokens iteration to ensure that the `byte_pos` is always correct.
|
||||
|
|
@ -1243,7 +1256,6 @@ impl<'src> Classifier<'src> {
|
|||
Class::MacroNonTerminal
|
||||
}
|
||||
TokenKind::Ident => {
|
||||
let file_span = self.file_span;
|
||||
let span = || new_span(before, text, file_span);
|
||||
|
||||
match text {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
// This test ensures that the macro expansion is correctly handled in cases like:
|
||||
// `field: !f!`, because the `:` was simply not considered because of how paths
|
||||
// are handled.
|
||||
|
||||
//@ compile-flags: -Zunstable-options --generate-macro-expansion
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
//@ has 'src/foo/field-followed-by-exclamation.rs.html'
|
||||
|
||||
struct Bar {
|
||||
bla: bool,
|
||||
}
|
||||
|
||||
macro_rules! f {
|
||||
() => {{ false }}
|
||||
}
|
||||
|
||||
const X: Bar = Bar {
|
||||
//@ has - '//*[@class="expansion"]/*[@class="original"]/*[@class="macro"]' 'f!'
|
||||
//@ has - '//*[@class="expansion"]/*[@class="original"]' 'f!()'
|
||||
//@ has - '//*[@class="expansion"]/*[@class="expanded"]' '{ false }'
|
||||
// It includes both original and expanded code.
|
||||
//@ has - '//*[@class="expansion"]' ' bla: !{ false }f!()'
|
||||
bla: !f!(),
|
||||
};
|
||||
|
|
@ -709,12 +709,6 @@ Tests on type inference.
|
|||
|
||||
Tests for diagnostics on infinitely recursive types without indirection.
|
||||
|
||||
## `tests/ui/inherent-impls-overlap-check/`
|
||||
|
||||
Checks that repeating the same function names across separate `impl` blocks triggers an informative error, but not if the `impl` are for different types, such as `Bar<u8>` and `Bar<u16>`.
|
||||
|
||||
NOTE: This should maybe be a subdirectory within another related to duplicate definitions, such as `tests/ui/duplicate/`.
|
||||
|
||||
## `tests/ui/inline-const/`
|
||||
|
||||
These tests revolve around the inline `const` block that forces the compiler to const-eval its content.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
//! regression test for <https://github.com/rust-lang/rust/issues/34074>
|
||||
//@ edition: 2015
|
||||
//@ check-pass
|
||||
// Make sure several unnamed function parameters don't conflict with each other
|
||||
|
|
@ -7,5 +8,4 @@ trait Tr {
|
|||
fn f(u8, u8) {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
//! regression test for <https://github.com/rust-lang/rust/issues/21306>
|
||||
//@ run-pass
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
fn main() {
|
||||
let x = 5;
|
||||
let command = Arc::new(Box::new(|| x * 2));
|
||||
assert_eq!(command(), 10);
|
||||
}
|
||||
5
tests/ui/consts/const-closure-fn-trait-object.rs
Normal file
5
tests/ui/consts/const-closure-fn-trait-object.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
//! regression test for <https://github.com/rust-lang/rust/issues/27268>
|
||||
//@ run-pass
|
||||
fn main() {
|
||||
const _C: &'static dyn Fn() = &|| {};
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
//! regression test for <https://github.com/rust-lang/rust/issues/19097>
|
||||
//@ check-pass
|
||||
#![allow(dead_code)]
|
||||
// regression test for #19097
|
||||
|
||||
struct Foo<T>(T);
|
||||
|
||||
|
|
@ -1,11 +1,12 @@
|
|||
//! regression test for <https://github.com/rust-lang/rust/issues/24161>
|
||||
//@ check-pass
|
||||
#![allow(dead_code)]
|
||||
#[derive(Copy,Clone)]
|
||||
#[derive(Copy, Clone)]
|
||||
struct Functions {
|
||||
a: fn(u32) -> u32,
|
||||
b: extern "C" fn(u32) -> u32,
|
||||
c: unsafe fn(u32) -> u32,
|
||||
d: unsafe extern "C" fn(u32) -> u32
|
||||
d: unsafe extern "C" fn(u32) -> u32,
|
||||
}
|
||||
|
||||
pub fn main() {}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
//! regression test for <https://github.com/rust-lang/rust/issues/23036>
|
||||
//@ run-pass
|
||||
|
||||
use std::collections::HashMap;
|
||||
16
tests/ui/inference/inference-thread-loop-closure.rs
Normal file
16
tests/ui/inference/inference-thread-loop-closure.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
//! regression test for <https://github.com/rust-lang/rust/issues/20454>
|
||||
//@ check-pass
|
||||
#![allow(unused_must_use)]
|
||||
use std::thread;
|
||||
|
||||
fn _foo() {
|
||||
thread::spawn(move || {
|
||||
// no need for -> ()
|
||||
loop {
|
||||
println!("hello");
|
||||
}
|
||||
})
|
||||
.join();
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
#![feature(rustc_attrs)]
|
||||
|
||||
#[rustc_lint_query_instability]
|
||||
//~^ ERROR attribute should be applied to a function
|
||||
//~^ ERROR `#[rustc_lint_query_instability]` attribute cannot be used on structs
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
|
|
|
|||
|
|
@ -1,17 +1,20 @@
|
|||
error: malformed `rustc_lint_query_instability` attribute input
|
||||
--> $DIR/query_stability_incorrect.rs:10:5
|
||||
|
|
||||
LL | #[rustc_lint_query_instability(a)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_lint_query_instability]`
|
||||
|
||||
error: attribute should be applied to a function definition
|
||||
error: `#[rustc_lint_query_instability]` attribute cannot be used on structs
|
||||
--> $DIR/query_stability_incorrect.rs:5:1
|
||||
|
|
||||
LL | #[rustc_lint_query_instability]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL |
|
||||
LL | struct Foo;
|
||||
| ----------- not a function definition
|
||||
|
|
||||
= help: `#[rustc_lint_query_instability]` can only be applied to functions
|
||||
|
||||
error[E0565]: malformed `rustc_lint_query_instability` attribute input
|
||||
--> $DIR/query_stability_incorrect.rs:10:5
|
||||
|
|
||||
LL | #[rustc_lint_query_instability(a)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---^
|
||||
| | |
|
||||
| | didn't expect any arguments here
|
||||
| help: must be of the form: `#[rustc_lint_query_instability]`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0565`.
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
//@ check-pass
|
||||
#![allow(unused_must_use)]
|
||||
use std::thread;
|
||||
|
||||
fn _foo() {
|
||||
thread::spawn(move || { // no need for -> ()
|
||||
loop {
|
||||
println!("hello");
|
||||
}
|
||||
}).join();
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
//@ run-pass
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
fn main() {
|
||||
let x = 5;
|
||||
let command = Arc::new(Box::new(|| { x*2 }));
|
||||
assert_eq!(command(), 10);
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
//@ build-pass
|
||||
#![allow(dead_code)]
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
||||
|
||||
static foo: [usize; 3] = [1, 2, 3];
|
||||
|
||||
static slice_1: &'static [usize] = &foo;
|
||||
static slice_2: &'static [usize] = &foo;
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
//@ run-pass
|
||||
fn main() {
|
||||
const _C: &'static dyn Fn() = &||{};
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
//@ check-pass
|
||||
|
||||
fn main() {
|
||||
assert!({false});
|
||||
|
||||
assert!(r"\u{41}" == "A");
|
||||
|
||||
assert!(r"\u{".is_empty());
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
//! regression test for <https://github.com/rust-lang/rust/issues/29540>
|
||||
//@ build-pass
|
||||
#[derive(Debug)]
|
||||
pub struct Config {
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
//! regression test for <https://github.com/rust-lang/rust/issues/26646>
|
||||
//@ check-pass
|
||||
#![deny(unused_attributes)]
|
||||
|
||||
|
|
@ -9,4 +10,4 @@ pub struct Foo;
|
|||
#[repr(C)]
|
||||
pub struct Bar;
|
||||
|
||||
fn main() { }
|
||||
fn main() {}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
//! regression test for <https://github.com/rust-lang/rust/issues/37686>
|
||||
//@ run-pass
|
||||
fn main() {
|
||||
match (0, 0) {
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
//! regression test for <https://github.com/rust-lang/rust/issues/38987>
|
||||
//@ run-pass
|
||||
fn main() {
|
||||
let _ = -0x8000_0000_0000_0000_0000_0000_0000_0000i128;
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
//! regression test for <https://github.com/rust-lang/rust/issues/18352>
|
||||
//@ run-pass
|
||||
|
||||
const X: &'static str = "12345";
|
||||
|
|
@ -5,7 +6,7 @@ const X: &'static str = "12345";
|
|||
fn test(s: String) -> bool {
|
||||
match &*s {
|
||||
X => true,
|
||||
_ => false
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
10
tests/ui/static/static-array-shared-slice-references.rs
Normal file
10
tests/ui/static/static-array-shared-slice-references.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
//! regression test for <https://github.com/rust-lang/rust/issues/21891>
|
||||
//@ build-pass
|
||||
#![allow(dead_code)]
|
||||
|
||||
static FOO: [usize; 3] = [1, 2, 3];
|
||||
|
||||
static SLICE_1: &'static [usize] = &FOO;
|
||||
static SLICE_2: &'static [usize] = &FOO;
|
||||
|
||||
fn main() {}
|
||||
10
tests/ui/str/raw-string-literal-unescaped-unicode.rs
Normal file
10
tests/ui/str/raw-string-literal-unescaped-unicode.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
//! regression test for <https://github.com/rust-lang/rust/issues/50471>
|
||||
//@ check-pass
|
||||
|
||||
fn main() {
|
||||
assert!({ false });
|
||||
|
||||
assert!(r"\u{41}" == "A");
|
||||
|
||||
assert!(r"\u{".is_empty());
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue