Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/crate_level.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,27 @@ impl<S: Stage> SingleAttributeParser<S> for PatternComplexityLimitParser {
})
}
}

pub(crate) struct NoCoreParser;

impl<S: Stage> NoArgsAttributeParser<S> for NoCoreParser {
const PATH: &[Symbol] = &[sym::no_core];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
// because it's a crate-level attribute, we already warn about it.
// Putting target limitations here would give duplicate warnings
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoCore;
const TYPE: AttributeType = AttributeType::CrateLevel;
}

pub(crate) struct NoStdParser;

impl<S: Stage> NoArgsAttributeParser<S> for NoStdParser {
const PATH: &[Symbol] = &[sym::no_std];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
// because it's a crate-level attribute, we already warn about it.
// Putting target limitations here would give duplicate warnings
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoStd;
const TYPE: AttributeType = AttributeType::CrateLevel;
}
6 changes: 4 additions & 2 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ use crate::attributes::codegen_attrs::{
};
use crate::attributes::confusables::ConfusablesParser;
use crate::attributes::crate_level::{
CrateNameParser, MoveSizeLimitParser, PatternComplexityLimitParser, RecursionLimitParser,
TypeLengthLimitParser,
CrateNameParser, MoveSizeLimitParser, NoCoreParser, NoStdParser, PatternComplexityLimitParser,
RecursionLimitParser, TypeLengthLimitParser,
};
use crate::attributes::deprecation::DeprecationParser;
use crate::attributes::dummy::DummyParser;
Expand Down Expand Up @@ -223,8 +223,10 @@ attribute_parsers!(
Single<WithoutArgs<MacroEscapeParser>>,
Single<WithoutArgs<MarkerParser>>,
Single<WithoutArgs<MayDangleParser>>,
Single<WithoutArgs<NoCoreParser>>,
Single<WithoutArgs<NoImplicitPreludeParser>>,
Single<WithoutArgs<NoMangleParser>>,
Single<WithoutArgs<NoStdParser>>,
Single<WithoutArgs<NonExhaustiveParser>>,
Single<WithoutArgs<ParenSugarParser>>,
Single<WithoutArgs<PassByValueParser>>,
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_hir/src/attrs/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -579,12 +579,18 @@ pub enum AttributeKind {
/// Represents `#[naked]`
Naked(Span),

/// Represents `#[no_core]`
NoCore(Span),

/// Represents `#[no_implicit_prelude]`
NoImplicitPrelude(Span),

/// Represents `#[no_mangle]`
NoMangle(Span),

/// Represents `#[no_std]`
NoStd(Span),

/// Represents `#[non_exhaustive]`
NonExhaustive(Span),

Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_hir/src/attrs/encode_cross_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,10 @@ impl AttributeKind {
MoveSizeLimit { .. } => No,
MustUse { .. } => Yes,
Naked(..) => No,
NoCore(..) => No,
NoImplicitPrelude(..) => No,
NoMangle(..) => Yes, // Needed for rustdoc
NoMangle(..) => Yes, // Needed for rustdoc
NoStd(..) => No,
NonExhaustive(..) => Yes, // Needed for rustdoc
Optimize(..) => No,
ParenSugar(..) => No,
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| AttributeKind::MoveSizeLimit { .. }
| AttributeKind::TypeLengthLimit { .. }
| AttributeKind::PatternComplexityLimit { .. }
| AttributeKind::NoCore { .. }
| AttributeKind::NoStd { .. }
) => { /* do nothing */ }
Attribute::Unparsed(attr_item) => {
style = Some(attr_item.style);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ use rustc_middle::ty::print::{
with_forced_trimmed_paths,
};
use rustc_middle::ty::{
self, TraitRef, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
Upcast,
self, GenericArgKind, TraitRef, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
TypeVisitableExt, Upcast,
};
use rustc_middle::{bug, span_bug};
use rustc_span::{BytePos, DUMMY_SP, STDLIB_STABLE_CRATES, Span, Symbol, sym};
Expand Down Expand Up @@ -2316,7 +2316,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
cand
})
.collect();
impl_candidates.sort_by_key(|cand| (cand.similarity, cand.trait_ref.to_string()));
impl_candidates.sort_by_key(|cand| {
// When suggesting array types, sort them by the length of the array, not lexicographically (#135098)
let len = if let GenericArgKind::Type(ty) = cand.trait_ref.args[0].kind()
&& let ty::Array(_, len) = ty.kind()
{
// Deprioritize suggestions for parameterized arrays.
len.try_to_target_usize(self.tcx).unwrap_or(u64::MAX)
} else {
0
};

(cand.similarity, len, cand.trait_ref.to_string())
});
let mut impl_candidates: Vec<_> =
impl_candidates.into_iter().map(|cand| cand.trait_ref).collect();
impl_candidates.dedup();
Expand Down
24 changes: 24 additions & 0 deletions library/coretests/tests/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,30 @@ fn layout_array_edge_cases() {
}
}

#[test]
fn layout_errors() {
let layout = Layout::new::<[u8; 2]>();
// Should error if the alignment is not a power of two.
assert!(layout.align_to(3).is_err());

// The remaining assertions ensure that the methods error on arithmetic overflow as the
// alignment cannot overflow `isize`.
let size = layout.size();
let size_max = isize::MAX as usize;
let align_max = size_max / size;

assert!(layout.align_to(size_max + 1).is_err());

assert!(layout.repeat(align_max).is_ok());
assert!(layout.repeat(align_max + 1).is_err());

assert!(layout.repeat_packed(align_max).is_ok());
assert!(layout.repeat_packed(align_max + 1).is_err());

let next = Layout::from_size_align(size_max, 1).unwrap();
assert!(layout.extend(next).is_err());
}

#[test]
fn layout_debug_shows_log2_of_alignment() {
// `Debug` is not stable, but here's what it does right now
Expand Down
43 changes: 43 additions & 0 deletions library/coretests/tests/char.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ fn test_escape_default() {
}
assert_eq!(string('\n'), "\\n");
assert_eq!(string('\r'), "\\r");
assert_eq!(string('\t'), "\\t");
assert_eq!(string('\''), "\\'");
assert_eq!(string('"'), "\\\"");
assert_eq!(string(' '), " ");
Expand Down Expand Up @@ -417,3 +418,45 @@ fn eu_iterator_specializations() {
check('\u{12340}');
check('\u{10FFFF}');
}

#[test]
#[should_panic]
fn test_from_digit_radix_too_high() {
let _ = char::from_digit(0, 37);
}

#[test]
fn test_from_digit_invalid_radix() {
assert!(char::from_digit(10, 9).is_none());
}

#[test]
#[should_panic]
fn test_to_digit_radix_too_low() {
let _ = 'a'.to_digit(1);
}

#[test]
#[should_panic]
fn test_to_digit_radix_too_high() {
let _ = 'a'.to_digit(37);
}

#[test]
fn test_as_ascii_invalid() {
assert!('❤'.as_ascii().is_none());
}

#[test]
#[should_panic]
fn test_encode_utf8_raw_buffer_too_small() {
let mut buf = [0u8; 1];
let _ = char::encode_utf8_raw('ß'.into(), &mut buf);
}

#[test]
#[should_panic]
fn test_encode_utf16_raw_buffer_too_small() {
let mut buf = [0u16; 1];
let _ = char::encode_utf16_raw('𐐷'.into(), &mut buf);
}
13 changes: 13 additions & 0 deletions library/coretests/tests/hash/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,14 @@ fn test_writer_hasher() {
assert_eq!(hash(&5_u16), 5);
assert_eq!(hash(&5_u32), 5);
assert_eq!(hash(&5_u64), 5);
assert_eq!(hash(&5_u128), 5);
assert_eq!(hash(&5_usize), 5);

assert_eq!(hash(&5_i8), 5);
assert_eq!(hash(&5_i16), 5);
assert_eq!(hash(&5_i32), 5);
assert_eq!(hash(&5_i64), 5);
assert_eq!(hash(&5_i128), 5);
assert_eq!(hash(&5_isize), 5);

assert_eq!(hash(&false), 0);
Expand All @@ -85,6 +87,17 @@ fn test_writer_hasher() {
let ptr = ptr::without_provenance_mut::<i32>(5_usize);
assert_eq!(hash(&ptr), 5);

// Use a newtype to test the `Hash::hash_slice` default implementation.
struct Byte(u8);

impl Hash for Byte {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_u8(self.0)
}
}

assert_eq!(hash(&[Byte(b'a')]), 97 + 1);

if cfg!(miri) {
// Miri cannot hash pointers
return;
Expand Down
1 change: 1 addition & 0 deletions library/coretests/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#![feature(bool_to_result)]
#![feature(bstr)]
#![feature(cfg_target_has_reliable_f16_f128)]
#![feature(char_internals)]
#![feature(char_max_len)]
#![feature(clone_to_uninit)]
#![feature(const_cmp)]
Expand Down
10 changes: 2 additions & 8 deletions src/tools/clippy/clippy_utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2133,17 +2133,11 @@ pub fn std_or_core(cx: &LateContext<'_>) -> Option<&'static str> {
}

pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool {
cx.tcx
.hir_attrs(hir::CRATE_HIR_ID)
.iter()
.any(|attr| attr.has_name(sym::no_std))
find_attr!(cx.tcx.hir_attrs(hir::CRATE_HIR_ID), AttributeKind::NoStd(..))
}

pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool {
cx.tcx
.hir_attrs(hir::CRATE_HIR_ID)
.iter()
.any(|attr| attr.has_name(sym::no_core))
find_attr!(cx.tcx.hir_attrs(hir::CRATE_HIR_ID), AttributeKind::NoCore(..))
}

/// Check if parent of a hir node is a trait implementation block.
Expand Down
25 changes: 25 additions & 0 deletions tests/ui/attributes/malformed-no-std.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#![feature(no_core)]
// these all still apply no_std and then later error
#![no_std = "foo"]
//~^ ERROR malformed `no_std` attribute input
#![no_std("bar")]
//~^ ERROR malformed `no_std` attribute input
#![no_std(foo = "bar")]
//~^ ERROR malformed `no_std` attribute input
#![no_core = "foo"]
//~^ ERROR malformed `no_core` attribute input
#![no_core("bar")]
//~^ ERROR malformed `no_core` attribute input
#![no_core(foo = "bar")]
//~^ ERROR malformed `no_core` attribute input

#[deny(unused_attributes)]
#[no_std]
//~^ ERROR crate-level attribute should be an inner attribute: add an exclamation mark:
#[no_core]
//~^ ERROR crate-level attribute should be an inner attribute: add an exclamation mark:
// to fix compilation
extern crate core;
extern crate std;

fn main() {}
86 changes: 86 additions & 0 deletions tests/ui/attributes/malformed-no-std.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
error[E0565]: malformed `no_std` attribute input
--> $DIR/malformed-no-std.rs:3:1
|
LL | #![no_std = "foo"]
| ^^^^^^^^^^-------^
| | |
| | didn't expect any arguments here
| help: must be of the form: `#![no_std]`

error[E0565]: malformed `no_std` attribute input
--> $DIR/malformed-no-std.rs:5:1
|
LL | #![no_std("bar")]
| ^^^^^^^^^-------^
| | |
| | didn't expect any arguments here
| help: must be of the form: `#![no_std]`

error[E0565]: malformed `no_std` attribute input
--> $DIR/malformed-no-std.rs:7:1
|
LL | #![no_std(foo = "bar")]
| ^^^^^^^^^-------------^
| | |
| | didn't expect any arguments here
| help: must be of the form: `#![no_std]`

error[E0565]: malformed `no_core` attribute input
--> $DIR/malformed-no-std.rs:9:1
|
LL | #![no_core = "foo"]
| ^^^^^^^^^^^-------^
| | |
| | didn't expect any arguments here
| help: must be of the form: `#![no_core]`

error[E0565]: malformed `no_core` attribute input
--> $DIR/malformed-no-std.rs:11:1
|
LL | #![no_core("bar")]
| ^^^^^^^^^^-------^
| | |
| | didn't expect any arguments here
| help: must be of the form: `#![no_core]`

error[E0565]: malformed `no_core` attribute input
--> $DIR/malformed-no-std.rs:13:1
|
LL | #![no_core(foo = "bar")]
| ^^^^^^^^^^-------------^
| | |
| | didn't expect any arguments here
| help: must be of the form: `#![no_core]`

error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_std]`
--> $DIR/malformed-no-std.rs:17:1
|
LL | #[no_std]
| ^^^^^^^^^
|
note: This attribute does not have an `!`, which means it is applied to this extern crate
--> $DIR/malformed-no-std.rs:22:1
|
LL | extern crate core;
| ^^^^^^^^^^^^^^^^^^
note: the lint level is defined here
--> $DIR/malformed-no-std.rs:16:8
|
LL | #[deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^

error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_core]`
--> $DIR/malformed-no-std.rs:19:1
|
LL | #[no_core]
| ^^^^^^^^^^
|
note: This attribute does not have an `!`, which means it is applied to this extern crate
--> $DIR/malformed-no-std.rs:22:1
|
LL | extern crate core;
| ^^^^^^^^^^^^^^^^^^

error: aborting due to 8 previous errors

For more information about this error, try `rustc --explain E0565`.
10 changes: 5 additions & 5 deletions tests/ui/consts/missing-larger-array-impl.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ LL | <[X; 35] as Default>::default();
&[T]
&mut [T]
[T; 0]
[T; 10]
[T; 11]
[T; 12]
[T; 13]
[T; 14]
[T; 1]
[T; 2]
[T; 3]
[T; 4]
[T; 5]
and 27 others

error: aborting due to 1 previous error
Expand Down
Loading
Loading