Auto merge of #93689 - matthiaskrgr:rollup-3pd1ept, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - #91939 (Clarify error on casting larger integers to char)
 - #92300 (mips64-openwrt-linux-musl: Add Tier 3 target)
 - #92383 (Add new target armv7-unknown-linux-uclibceabi (softfloat))
 - #92651 (Remove "up here" arrow on item-infos)
 - #93556 (Change struct expr pretty printing to match rustfmt style)
 - #93649 (Add regression tests for issue 80309)
 - #93657 (Update CPU idle tracking for apple hosts)
 - #93659 (Refactor conditional)
 - #93669 (Resolve lifetimes for const generic defaults)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-02-06 05:54:07 +00:00
commit e069a71108
36 changed files with 523 additions and 132 deletions

View file

@ -148,7 +148,7 @@ pub enum Breaks {
Inconsistent, Inconsistent,
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy, PartialEq)]
enum IndentStyle { enum IndentStyle {
/// Vertically aligned under whatever column this block begins at. /// Vertically aligned under whatever column this block begins at.
/// ///
@ -164,19 +164,20 @@ enum IndentStyle {
Block { offset: isize }, Block { offset: isize },
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy, Default, PartialEq)]
pub struct BreakToken { pub struct BreakToken {
offset: isize, offset: isize,
blank_space: isize, blank_space: isize,
pre_break: Option<char>,
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy, PartialEq)]
pub struct BeginToken { pub struct BeginToken {
indent: IndentStyle, indent: IndentStyle,
breaks: Breaks, breaks: Breaks,
} }
#[derive(Clone)] #[derive(Clone, PartialEq)]
pub enum Token { pub enum Token {
// In practice a string token contains either a `&'static str` or a // In practice a string token contains either a `&'static str` or a
// `String`. `Cow` is overkill for this because we never modify the data, // `String`. `Cow` is overkill for this because we never modify the data,
@ -313,6 +314,12 @@ fn scan_string(&mut self, string: Cow<'static, str>) {
} }
} }
pub fn offset(&mut self, offset: isize) {
if let Some(BufEntry { token: Token::Break(token), .. }) = &mut self.buf.last_mut() {
token.offset += offset;
}
}
fn check_stream(&mut self) { fn check_stream(&mut self) {
while self.right_total - self.left_total > self.space { while self.right_total - self.left_total > self.space {
if *self.scan_stack.front().unwrap() == self.buf.index_of_first() { if *self.scan_stack.front().unwrap() == self.buf.index_of_first() {
@ -391,7 +398,9 @@ fn print_begin(&mut self, token: BeginToken, size: isize) {
if size > self.space { if size > self.space {
self.print_stack.push(PrintFrame::Broken { indent: self.indent, breaks: token.breaks }); self.print_stack.push(PrintFrame::Broken { indent: self.indent, breaks: token.breaks });
self.indent = match token.indent { self.indent = match token.indent {
IndentStyle::Block { offset } => (self.indent as isize + offset) as usize, IndentStyle::Block { offset } => {
usize::try_from(self.indent as isize + offset).unwrap()
}
IndentStyle::Visual => (MARGIN - self.space) as usize, IndentStyle::Visual => (MARGIN - self.space) as usize,
}; };
} else { } else {
@ -415,6 +424,9 @@ fn print_break(&mut self, token: BreakToken, size: isize) {
self.pending_indentation += token.blank_space; self.pending_indentation += token.blank_space;
self.space -= token.blank_space; self.space -= token.blank_space;
} else { } else {
if let Some(pre_break) = token.pre_break {
self.out.push(pre_break);
}
self.out.push('\n'); self.out.push('\n');
let indent = self.indent as isize + token.offset; let indent = self.indent as isize + token.offset;
self.pending_indentation = indent; self.pending_indentation = indent;

View file

@ -3,20 +3,17 @@
impl Printer { impl Printer {
/// "raw box" /// "raw box"
pub fn rbox(&mut self, indent: usize, breaks: Breaks) { pub fn rbox(&mut self, indent: isize, breaks: Breaks) {
self.scan_begin(BeginToken { self.scan_begin(BeginToken { indent: IndentStyle::Block { offset: indent }, breaks })
indent: IndentStyle::Block { offset: indent as isize },
breaks,
})
} }
/// Inconsistent breaking box /// Inconsistent breaking box
pub fn ibox(&mut self, indent: usize) { pub fn ibox(&mut self, indent: isize) {
self.rbox(indent, Breaks::Inconsistent) self.rbox(indent, Breaks::Inconsistent)
} }
/// Consistent breaking box /// Consistent breaking box
pub fn cbox(&mut self, indent: usize) { pub fn cbox(&mut self, indent: isize) {
self.rbox(indent, Breaks::Consistent) self.rbox(indent, Breaks::Consistent)
} }
@ -25,7 +22,11 @@ pub fn visual_align(&mut self) {
} }
pub fn break_offset(&mut self, n: usize, off: isize) { pub fn break_offset(&mut self, n: usize, off: isize) {
self.scan_break(BreakToken { offset: off, blank_space: n as isize }) self.scan_break(BreakToken {
offset: off,
blank_space: n as isize,
..BreakToken::default()
});
} }
pub fn end(&mut self) { pub fn end(&mut self) {
@ -66,12 +67,24 @@ pub fn is_beginning_of_line(&self) -> bool {
} }
pub fn hardbreak_tok_offset(off: isize) -> Token { pub fn hardbreak_tok_offset(off: isize) -> Token {
Token::Break(BreakToken { offset: off, blank_space: SIZE_INFINITY }) Token::Break(BreakToken {
offset: off,
blank_space: SIZE_INFINITY,
..BreakToken::default()
})
}
pub fn trailing_comma(&mut self) {
self.scan_break(BreakToken {
blank_space: 1,
pre_break: Some(','),
..BreakToken::default()
});
} }
} }
impl Token { impl Token {
pub fn is_hardbreak_tok(&self) -> bool { pub fn is_hardbreak_tok(&self) -> bool {
matches!(self, Token::Break(BreakToken { offset: 0, blank_space: SIZE_INFINITY })) *self == Printer::hardbreak_tok_offset(0)
} }
} }

View file

@ -1,3 +1,4 @@
mod delimited;
mod expr; mod expr;
mod item; mod item;
@ -23,6 +24,8 @@
use std::borrow::Cow; use std::borrow::Cow;
pub use self::delimited::IterDelimited;
pub enum MacHeader<'a> { pub enum MacHeader<'a> {
Path(&'a ast::Path), Path(&'a ast::Path),
Keyword(&'static str), Keyword(&'static str),
@ -92,7 +95,7 @@ pub struct State<'a> {
ann: &'a (dyn PpAnn + 'a), ann: &'a (dyn PpAnn + 'a),
} }
crate const INDENT_UNIT: usize = 4; crate const INDENT_UNIT: isize = 4;
/// Requires you to pass an input filename and reader so that /// Requires you to pass an input filename and reader so that
/// it can scan the input text for comments to copy forward. /// it can scan the input text for comments to copy forward.

View file

@ -0,0 +1,41 @@
use std::iter::Peekable;
use std::mem;
use std::ops::Deref;
pub struct Delimited<I: Iterator> {
is_first: bool,
iter: Peekable<I>,
}
pub trait IterDelimited: Iterator + Sized {
fn delimited(self) -> Delimited<Self> {
Delimited { is_first: true, iter: self.peekable() }
}
}
impl<I: Iterator> IterDelimited for I {}
pub struct IteratorItem<T> {
value: T,
pub is_first: bool,
pub is_last: bool,
}
impl<I: Iterator> Iterator for Delimited<I> {
type Item = IteratorItem<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
let value = self.iter.next()?;
let is_first = mem::replace(&mut self.is_first, false);
let is_last = self.iter.peek().is_none();
Some(IteratorItem { value, is_first, is_last })
}
}
impl<T> Deref for IteratorItem<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.value
}
}

View file

@ -1,5 +1,5 @@
use crate::pp::Breaks::{Consistent, Inconsistent}; use crate::pp::Breaks::Inconsistent;
use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT}; use crate::pprust::state::{AnnNode, IterDelimited, PrintState, State, INDENT_UNIT};
use rustc_ast::ptr::P; use rustc_ast::ptr::P;
use rustc_ast::util::parser::{self, AssocOp, Fixity}; use rustc_ast::util::parser::{self, AssocOp, Fixity};
@ -117,38 +117,46 @@ fn print_expr_struct(
} else { } else {
self.print_path(path, true, 0); self.print_path(path, true, 0);
} }
self.nbsp();
self.word("{"); self.word("{");
self.commasep_cmnt( let has_rest = match rest {
Consistent, ast::StructRest::Base(_) | ast::StructRest::Rest(_) => true,
fields, ast::StructRest::None => false,
|s, field| { };
s.print_outer_attributes(&field.attrs); if fields.is_empty() && !has_rest {
s.ibox(INDENT_UNIT); self.word("}");
if !field.is_shorthand { return;
s.print_ident(field.ident);
s.word_space(":");
}
s.print_expr(&field.expr);
s.end();
},
|f| f.span,
);
match rest {
ast::StructRest::Base(_) | ast::StructRest::Rest(_) => {
self.ibox(INDENT_UNIT);
if !fields.is_empty() {
self.word(",");
self.space();
}
self.word("..");
if let ast::StructRest::Base(ref expr) = *rest {
self.print_expr(expr);
}
self.end();
}
ast::StructRest::None if !fields.is_empty() => self.word(","),
_ => {}
} }
self.cbox(0);
for field in fields.iter().delimited() {
self.maybe_print_comment(field.span.hi());
self.print_outer_attributes(&field.attrs);
if field.is_first {
self.space_if_not_bol();
}
if !field.is_shorthand {
self.print_ident(field.ident);
self.word_nbsp(":");
}
self.print_expr(&field.expr);
if !field.is_last || has_rest {
self.word_space(",");
} else {
self.trailing_comma();
}
}
if has_rest {
if fields.is_empty() {
self.space();
}
self.word("..");
if let ast::StructRest::Base(expr) = rest {
self.print_expr(expr);
}
self.space();
}
self.offset(-INDENT_UNIT);
self.end();
self.word("}"); self.word("}");
} }

View file

@ -6,11 +6,16 @@ Erroneous code example:
0u32 as char; // error: only `u8` can be cast as `char`, not `u32` 0u32 as char; // error: only `u8` can be cast as `char`, not `u32`
``` ```
As the error message indicates, only `u8` can be cast into `char`. Example: `char` is a Unicode Scalar Value, an integer value from 0 to 0xD7FF and
0xE000 to 0x10FFFF. (The gap is for surrogate pairs.) Only `u8` always fits in
those ranges so only `u8` may be cast to `char`.
To allow larger values, use `char::from_u32`, which checks the value is valid.
``` ```
let c = 86u8 as char; // ok! assert_eq!(86u8 as char, 'V'); // ok!
assert_eq!(c, 'V'); assert_eq!(char::from_u32(0x3B1), Some('α')); // ok!
assert_eq!(char::from_u32(0xD800), None); // not a USV.
``` ```
For more information about casts, take a look at the Type cast section in For more information about casts, take a look at the Type cast section in

View file

@ -139,7 +139,7 @@ fn print_generic_args(&mut self, _: &ast::GenericArgs, _colons_before_params: bo
} }
} }
pub const INDENT_UNIT: usize = 4; pub const INDENT_UNIT: isize = 4;
/// Requires you to pass an input filename and reader so that /// Requires you to pass an input filename and reader so that
/// it can scan the input text for comments to copy forward. /// it can scan the input text for comments to copy forward.

View file

@ -1339,11 +1339,14 @@ fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
this.visit_ty(&ty); this.visit_ty(&ty);
} }
} }
GenericParamKind::Const { ref ty, .. } => { GenericParamKind::Const { ref ty, default } => {
let was_in_const_generic = this.is_in_const_generic; let was_in_const_generic = this.is_in_const_generic;
this.is_in_const_generic = true; this.is_in_const_generic = true;
walk_list!(this, visit_param_bound, param.bounds); walk_list!(this, visit_param_bound, param.bounds);
this.visit_ty(&ty); this.visit_ty(&ty);
if let Some(default) = default {
this.visit_body(this.tcx.hir().body(default.body));
}
this.is_in_const_generic = was_in_const_generic; this.is_in_const_generic = was_in_const_generic;
} }
} }

View file

@ -0,0 +1,23 @@
use crate::spec::{Target, TargetOptions};
// This target is for uclibc Linux on ARMv7 without NEON,
// thumb-mode or hardfloat.
pub fn target() -> Target {
let base = super::linux_uclibc_base::opts();
Target {
llvm_target: "armv7-unknown-linux-gnueabi".to_string(),
pointer_width: 32,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
options: TargetOptions {
features: "+v7,+thumb2,+soft-float,-neon".to_string(),
cpu: "generic".to_string(),
max_atomic_width: Some(64),
mcount: "_mcount".to_string(),
abi: "eabi".to_string(),
..base
},
}
}

View file

@ -0,0 +1,26 @@
/// A target tuple for OpenWrt MIPS64 targets
///
use crate::abi::Endian;
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::linux_musl_base::opts();
base.cpu = "mips64r2".to_string();
base.features = "+mips64r2".to_string();
base.max_atomic_width = Some(64);
base.crt_static_default = false;
Target {
// LLVM doesn't recognize "muslabi64" yet.
llvm_target: "mips64-unknown-linux-musl".to_string(),
pointer_width: 64,
data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
arch: "mips64".to_string(),
options: TargetOptions {
abi: "abi64".to_string(),
endian: Endian::Big,
mcount: "_mcount".to_string(),
..base
},
}
}

View file

@ -1013,9 +1013,12 @@ fn $module() {
("armv6k-nintendo-3ds", armv6k_nintendo_3ds), ("armv6k-nintendo-3ds", armv6k_nintendo_3ds),
("armv7-unknown-linux-uclibceabi", armv7_unknown_linux_uclibceabi),
("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf), ("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf),
("x86_64-unknown-none", x86_64_unknown_none), ("x86_64-unknown-none", x86_64_unknown_none),
("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl),
} }
/// Warnings encountered when parsing the target `json`. /// Warnings encountered when parsing the target `json`.

View file

@ -328,16 +328,28 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError) {
err.emit(); err.emit();
} }
CastError::CastToChar => { CastError::CastToChar => {
type_error_struct!( let mut err = type_error_struct!(
fcx.tcx.sess, fcx.tcx.sess,
self.span, self.span,
self.expr_ty, self.expr_ty,
E0604, E0604,
"only `u8` can be cast as `char`, not `{}`", "only `u8` can be cast as `char`, not `{}`",
self.expr_ty self.expr_ty
) );
.span_label(self.span, "invalid cast") err.span_label(self.span, "invalid cast");
.emit(); if self.expr_ty.is_numeric() {
err.span_help(
self.span,
if self.expr_ty == fcx.tcx.types.i8 {
"try casting from `u8` instead"
} else if self.expr_ty == fcx.tcx.types.u32 {
"try `char::from_u32` instead"
} else {
"try `char::from_u32` instead (via a `u32`)"
},
);
}
err.emit();
} }
CastError::NonScalar => { CastError::NonScalar => {
let mut err = type_error_struct!( let mut err = type_error_struct!(

View file

@ -108,37 +108,37 @@ elif sys.platform == 'darwin':
from ctypes import * from ctypes import *
libc = cdll.LoadLibrary('/usr/lib/libc.dylib') libc = cdll.LoadLibrary('/usr/lib/libc.dylib')
PROESSOR_CPU_LOAD_INFO = c_int(2) class host_cpu_load_info_data_t(Structure):
_fields_ = [("cpu_ticks", c_uint * 4)]
host_statistics = libc.host_statistics
host_statistics.argtypes = [
c_uint,
c_int,
POINTER(host_cpu_load_info_data_t),
POINTER(c_int)
]
host_statistics.restype = c_int
CPU_STATE_USER = 0 CPU_STATE_USER = 0
CPU_STATE_SYSTEM = 1 CPU_STATE_SYSTEM = 1
CPU_STATE_IDLE = 2 CPU_STATE_IDLE = 2
CPU_STATE_NICE = 3 CPU_STATE_NICE = 3
c_int_p = POINTER(c_int)
class State: class State:
def __init__(self): def __init__(self):
num_cpus_u = c_uint(0) stats = host_cpu_load_info_data_t()
cpu_info = c_int_p() count = c_int(4) # HOST_CPU_LOAD_INFO_COUNT
cpu_info_cnt = c_int(0) err = libc.host_statistics(
err = libc.host_processor_info(
libc.mach_host_self(), libc.mach_host_self(),
PROESSOR_CPU_LOAD_INFO, c_int(3), # HOST_CPU_LOAD_INFO
byref(num_cpus_u), byref(stats),
byref(cpu_info), byref(count),
byref(cpu_info_cnt),
) )
assert err == 0 assert err == 0
self.user = 0 self.system = stats.cpu_ticks[CPU_STATE_SYSTEM]
self.system = 0 self.user = stats.cpu_ticks[CPU_STATE_USER]
self.idle = 0 self.idle = stats.cpu_ticks[CPU_STATE_IDLE]
self.nice = 0 self.nice = stats.cpu_ticks[CPU_STATE_NICE]
cur = 0
while cur < cpu_info_cnt.value:
self.user += cpu_info[cur + CPU_STATE_USER]
self.system += cpu_info[cur + CPU_STATE_SYSTEM]
self.idle += cpu_info[cur + CPU_STATE_IDLE]
self.nice += cpu_info[cur + CPU_STATE_NICE]
cur += num_cpus_u.value
def idle_since(self, prev): def idle_since(self, prev):
user = self.user - prev.user user = self.user - prev.user

View file

@ -15,6 +15,7 @@
- [Platform Support](platform-support.md) - [Platform Support](platform-support.md)
- [Template for target-specific documentation](platform-support/TEMPLATE.md) - [Template for target-specific documentation](platform-support/TEMPLATE.md)
- [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md) - [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md)
- [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md)
- [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md) - [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md)
- [\*-kmc-solid_\*](platform-support/kmc-solid.md) - [\*-kmc-solid_\*](platform-support/kmc-solid.md)
- [*-unknown-openbsd](platform-support/openbsd.md) - [*-unknown-openbsd](platform-support/openbsd.md)

View file

@ -220,7 +220,8 @@ target | std | host | notes
`armv6-unknown-netbsd-eabihf` | ? | | `armv6-unknown-netbsd-eabihf` | ? | |
`armv6k-nintendo-3ds` | * | | ARMv6K Nintendo 3DS, Horizon (Requires devkitARM toolchain) `armv6k-nintendo-3ds` | * | | ARMv6K Nintendo 3DS, Horizon (Requires devkitARM toolchain)
`armv7-apple-ios` | ✓ | | ARMv7 iOS, Cortex-a8 `armv7-apple-ios` | ✓ | | ARMv7 iOS, Cortex-a8
[`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | ARMv7 Linux uClibc [`armv7-unknown-linux-uclibceabi`](platform-support/armv7-unknown-linux-uclibceabi.md) | ✓ | ✓ | ARMv7 Linux with uClibc, softfloat
[`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | ARMv7 Linux with uClibc, hardfloat
`armv7-unknown-freebsd` | ✓ | ✓ | ARMv7 FreeBSD `armv7-unknown-freebsd` | ✓ | ✓ | ARMv7 FreeBSD
`armv7-unknown-netbsd-eabihf` | ✓ | ✓ | `armv7-unknown-netbsd-eabihf` | ✓ | ✓ |
`armv7-wrs-vxworks-eabihf` | ? | | `armv7-wrs-vxworks-eabihf` | ? | |
@ -244,6 +245,7 @@ target | std | host | notes
`i686-wrs-vxworks` | ? | | `i686-wrs-vxworks` | ? | |
`m68k-unknown-linux-gnu` | ? | | Motorola 680x0 Linux `m68k-unknown-linux-gnu` | ? | | Motorola 680x0 Linux
`mips-unknown-linux-uclibc` | ✓ | | MIPS Linux with uClibc `mips-unknown-linux-uclibc` | ✓ | | MIPS Linux with uClibc
`mips64-openwrt-linux-musl` | ? | | MIPS64 for OpenWrt Linux MUSL
`mipsel-sony-psp` | * | | MIPS (LE) Sony PlayStation Portable (PSP) `mipsel-sony-psp` | * | | MIPS (LE) Sony PlayStation Portable (PSP)
`mipsel-unknown-linux-uclibc` | ✓ | | MIPS (LE) Linux with uClibc `mipsel-unknown-linux-uclibc` | ✓ | | MIPS (LE) Linux with uClibc
`mipsel-unknown-none` | * | | Bare MIPS (LE) softfloat `mipsel-unknown-none` | * | | Bare MIPS (LE) softfloat

View file

@ -0,0 +1,121 @@
# `armv7-unknown-linux-uclibceabi`
**Tier: 3**
This target supports ARMv7 softfloat CPUs and uses the uclibc-ng standard library. This is a common configuration on many consumer routers (e.g., Netgear R7000, Asus RT-AC68U).
## Target maintainers
* [@lancethepants](https://github.com/lancethepants)
## Requirements
This target is cross compiled, and requires a cross toolchain.
This target supports host tools and std.
## Building the target
You will need to download or build a `'C'` cross toolchain that targets ARMv7 softfloat and that uses the uclibc-ng standard library. If your target hardware is something like a router or an embedded device, keep in mind that manufacturer supplied SDKs for this class of CPU could be outdated and potentially unsuitable for bootstrapping rust.
[Here](https://github.com/lancethepants/tomatoware-toolchain) is a sample toolchain that is built using [buildroot](https://buildroot.org/). It uses modern toolchain components, older thus universal kernel headers (2.6.36.4), and is used for a project called [Tomatoware](https://github.com/lancethepants/tomatoware). This toolchain is patched so that its sysroot is located at /mmc (e.g., /mmc/bin, /mmc/lib, /mmc/include). This is useful in scenarios where the root filesystem is read-only but you are able attach external storage loaded with user applications. Tomatoware is an example of this that even allows you to run various compilers and developer tools natively on the target device.
Utilizing the Tomatoware toolchain this target can be built for cross compilation and native compilation (host tools) with project
[rust-bootstrap-armv7-unknown-linux-uclibceabi](https://github.com/lancethepants/rust-bootstrap-armv7-unknown-linux-uclibceabi).
Here is a sample config if using your own toolchain.
```toml
[build]
build-stage = 2
target = ["armv7-unknown-linux-uclibceabi"]
[target.armv7-unknown-linux-uclibceabi]
cc = "/path/to/arm-unknown-linux-uclibcgnueabi-gcc"
cxx = "/path/to/arm-unknown-linux-uclibcgnueabi-g++"
ar = "path/to/arm-unknown-linux-uclibcgnueabi-ar"
ranlib = "path/to/arm-unknown-linux-uclibcgnueabi-"
linker = "/path/to/arm-unknown-linux-uclibcgnueabi-"
```
## Building Rust programs
The following assumes you are using the Tomatoware toolchain and environment. Adapt if you are using your own toolchain.
### Native compilation
Since this target supports host tools, you can natively build rust applications directly on your target device. This can be convenient because it removes the complexities of cross compiling and you can immediately test and deploy your binaries. One downside is that compiling on your ARMv7 CPU will probably be much slower than cross compilation on your x86 machine.
To setup native compilation:
* Download Tomatoware to your device using the latest nightly release found [here](https://files.lancethepants.com/Tomatoware/Nightly/).
* Extract `tar zxvf arm-soft-mmc.tgz -C /mmc`
* Add `/mmc/bin:/mmc:sbin/` to your PATH, or `source /mmc/etc/profile`
* `apt update && apt install rust`
If you bootstrap rust on your own using the project above, it will create a .deb file that you then can install with
```text
dpkg -i rust_1.xx.x-x_arm.deb
```
After completing these steps you can use rust normally in a native environment.
### Cross Compilation
To cross compile, you'll need to:
* Build the rust cross toochain using [rust-bootstrap-armv7-unknown-linux-uclibceabi](https://github.com/lancethepants/rust-bootstrap-armv7-unknown-linux-uclibceabi) or your own built toolchain.
* Link your built toolchain with
```text
rustup toolchain link stage2 \
${HOME}/rust-bootstrap-armv7-unknown-linux-uclibceabi/src/rust/rust/build/x86_64-unknown-linux-gnu/stage2
```
* Build with:
```text
CC=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-gcc \
CXX=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-g++ \
AR=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-ar \
CARGO_TARGET_ARMV7_UNKNOWN_LINUX_UCLIBCEABI_LINKER=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-gcc \
CARGO_TARGET_ARMV7_UNKNOWN_LINUX_UCLIBCEABI_RUSTFLAGS='-Clink-arg=-s -Clink-arg=-Wl,--dynamic-linker=/mmc/lib/ld-uClibc.so.1 -Clink-arg=-Wl,-rpath,/mmc/lib' \
cargo +stage2 build --target armv7-unknown-linux-uclibceabi --release
```
* Copy the binary to your target device and run.
We specify `CC`, `CXX`, and `AR` because somtimes a project or a subproject requires the use of your `'C'` cross toolchain. Since Tomatoware has a modified sysroot we also pass via RUSTFLAGS the location of the dynamic-linker and rpath.
### Test with QEMU
To test a cross-compiled binary on your build system follow the instructions for `Cross Compilation`, install `qemu-arm-static`, and run with the following.
```text
CC=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-gcc \
CXX=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-g++ \
AR=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-ar \
CARGO_TARGET_ARMV7_UNKNOWN_LINUX_UCLIBCEABI_LINKER=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-gcc \
CARGO_TARGET_ARMV7_UNKNOWN_LINUX_UCLIBCEABI_RUNNER="qemu-arm-static -L /opt/tomatoware/arm-soft-mmc/arm-tomatoware-linux-uclibcgnueabi/sysroot/" \
cargo +stage2 run --target armv7-unknown-linux-uclibceabi --release
```
### Run in a chroot
It's also possible to build in a chroot environment. This is a convenient way to work without needing to access the target hardware.
To build the chroot:
* `sudo debootstrap --arch armel bullseye $HOME/debian`
* `sudo chroot $HOME/debian/ /bin/bash`
* `mount proc /proc -t proc`
* `mount -t sysfs /sys sys/`
* `export PATH=/mmc/bin:/mmc/sbin:$PATH`
From here you can setup your environment (e.g., add user, install wget).
* Download Tomatoware to the chroot environment using the latest nightly release found [here](https://files.lancethepants.com/Tomatoware/Nightly/).
* Extract `tar zxvf arm-soft-mmc.tgz -C /mmc`
* Add `/mmc/bin:/mmc:sbin/` to your PATH, or `source /mmc/etc/profile`
* `sudo /mmc/bin/apt update && sudo /mmc/bin/apt install rust`
After completing these steps you can use rust normally in a chroot environment.
Remember when using `sudo` the root user's PATH could differ from your user's PATH.

View file

@ -0,0 +1,28 @@
# `mips64-openwrt-linux-musl`
**Tier: 3**
## Target maintainers
- Donald Hoskins `grommish@gmail.com`, https://github.com/Itus-Shield
## Requirements
This target is cross-compiled. There is no support for `std`. There is no
default allocator, but it's possible to use `alloc` by supplying an allocator.
By default, Rust code generated for this target uses `-msoft-float` and is
dynamically linked.
This target generated binaries in the ELF format.
## Building the target
This target is built exclusively within the `OpenWrt` build system via
the `rust-lang` HOST package
## Building Rust programs
Rust does not yet ship pre-compiled artifacts for this target. To compile for
this target, you will either need to build Rust with the target enabled (see
"Building the target" above).
## Testing
As `mips64-openwrt-linux-musl` supports a variety of different environments and does
not support `std`, this target does not support running the Rust testsuite at this
time.

View file

@ -175,11 +175,13 @@ h3.code-header {
h4.code-header { h4.code-header {
font-size: 1rem; font-size: 1rem;
} }
h3.code-header, h4.code-header { .code-header {
font-weight: 600; font-weight: 600;
border-bottom-style: none; border-bottom-style: none;
padding: 0;
margin: 0; margin: 0;
padding: 0;
margin-top: 0.6em;
margin-bottom: 0.4em;
} }
.impl, .impl,
.impl-items .method, .impl-items .method,
@ -192,8 +194,6 @@ h3.code-header, h4.code-header {
.methods .associatedtype { .methods .associatedtype {
flex-basis: 100%; flex-basis: 100%;
font-weight: 600; font-weight: 600;
margin-top: 16px;
margin-bottom: 10px;
position: relative; position: relative;
} }
@ -744,21 +744,13 @@ nav.sub {
.content .item-info { .content .item-info {
position: relative; position: relative;
margin-left: 33px; margin-left: 24px;
} }
.sub-variant > div > .item-info { .sub-variant > div > .item-info {
margin-top: initial; margin-top: initial;
} }
.content .item-info::before {
content: '⬑';
font-size: 1.5625rem;
position: absolute;
top: -6px;
left: -19px;
}
.content .impl-items .docblock, .content .impl-items .item-info { .content .impl-items .docblock, .content .impl-items .item-info {
margin-bottom: .6em; margin-bottom: .6em;
} }
@ -777,6 +769,7 @@ nav.sub {
#main-content > .item-info { #main-content > .item-info {
margin-top: 0; margin-top: 0;
margin-left: 0;
} }
nav.sub { nav.sub {
@ -1125,13 +1118,6 @@ body.blur > :not(#help) {
float: right; float: right;
} }
.has-srclink {
font-size: 1rem;
margin-bottom: 12px;
/* Push the src link out to the right edge consistently */
justify-content: space-between;
}
.variants_table { .variants_table {
width: 100%; width: 100%;
} }
@ -2066,6 +2052,24 @@ details.rustdoc-toggle[open] > summary.hideme::after {
} }
} }
.method-toggle summary,
.implementors-toggle summary {
margin-bottom: 0.75em;
}
.method-toggle[open] {
margin-bottom: 2em;
}
.implementors-toggle[open] {
margin-bottom: 2em;
}
#trait-implementations-list .method-toggle,
#synthetic-implementations-list .method-toggle,
#blanket-implementations-list .method-toggle {
margin-bottom: 1em;
}
/* Begin: styles for --scrape-examples feature */ /* Begin: styles for --scrape-examples feature */

View file

@ -587,11 +587,8 @@ window.initSearch = function(rawSearchIndex) {
} }
function typePassesFilter(filter, type) { function typePassesFilter(filter, type) {
// No filter // No filter or Exact mach
if (filter <= NO_TYPE_FILTER) return true; if (filter <= NO_TYPE_FILTER || filter === type) return true;
// Exact match
if (filter === type) return true;
// Match related items // Match related items
var name = itemTypes[type]; var name = itemTypes[type];

View file

@ -119,9 +119,9 @@ fn syntax() {
let _ = #[attr] foo![#! [attr]]; let _ = #[attr] foo![#! [attr]];
let _ = #[attr] foo! {}; let _ = #[attr] foo! {};
let _ = #[attr] foo! { #! [attr] }; let _ = #[attr] foo! { #! [attr] };
let _ = #[attr] Foo{bar: baz,}; let _ = #[attr] Foo { bar: baz };
let _ = #[attr] Foo{..foo}; let _ = #[attr] Foo { ..foo };
let _ = #[attr] Foo{bar: baz, ..foo}; let _ = #[attr] Foo { bar: baz, ..foo };
let _ = #[attr] (0); let _ = #[attr] (0);
{ {

View file

@ -8,9 +8,10 @@ struct C {
#[allow()] #[allow()]
const C: C = const C: C =
C{ C {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
field: 0, field: 0,
#[cfg(not(debug_assertions))] #[cfg(not(debug_assertions))]
field: 1,}; field: 1,
};

View file

@ -90,9 +90,9 @@ struct Foo {
fn _7() { fn _7() {
#[rustc_dummy] #[rustc_dummy]
Foo{data: (),}; Foo { data: () };
let _ = #[rustc_dummy] Foo{data: (),}; let _ = #[rustc_dummy] Foo { data: () };
} }
fn _8() { fn _8() {
@ -209,7 +209,7 @@ fn _11() {
let mut x = 0; let mut x = 0;
let _ = #[rustc_dummy] x = 15; let _ = #[rustc_dummy] x = 15;
let _ = #[rustc_dummy] x += 15; let _ = #[rustc_dummy] x += 15;
let s = Foo{data: (),}; let s = Foo { data: () };
let _ = #[rustc_dummy] s.data; let _ = #[rustc_dummy] s.data;
let _ = (#[rustc_dummy] s).data; let _ = (#[rustc_dummy] s).data;
let t = Bar(()); let t = Bar(());
@ -235,9 +235,9 @@ fn _11() {
let _ = #[rustc_dummy] expr_mac!(); let _ = #[rustc_dummy] expr_mac!();
let _ = #[rustc_dummy] expr_mac![]; let _ = #[rustc_dummy] expr_mac![];
let _ = #[rustc_dummy] expr_mac! {}; let _ = #[rustc_dummy] expr_mac! {};
let _ = #[rustc_dummy] Foo{data: (),}; let _ = #[rustc_dummy] Foo { data: () };
let _ = #[rustc_dummy] Foo{..s}; let _ = #[rustc_dummy] Foo { ..s };
let _ = #[rustc_dummy] Foo{data: (), ..s}; let _ = #[rustc_dummy] Foo { data: (), ..s };
let _ = #[rustc_dummy] (0); let _ = #[rustc_dummy] (0);
} }

View file

@ -4,10 +4,6 @@ goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.borrow
assert-attribute: ("#blanket-implementations-list > details:nth-child(2)", {"open": ""}) assert-attribute: ("#blanket-implementations-list > details:nth-child(2)", {"open": ""})
// We first check that the impl block is open by default. // We first check that the impl block is open by default.
assert-attribute: ("#implementations + details", {"open": ""}) assert-attribute: ("#implementations + details", {"open": ""})
// We collapse it.
click: "#implementations + details > summary"
// We check that it was collapsed as expected.
assert-attribute-false: ("#implementations + details", {"open": ""})
// To ensure that we will click on the currently hidden method. // To ensure that we will click on the currently hidden method.
assert-text: (".sidebar-links > a", "must_use") assert-text: (".sidebar-links > a", "must_use")
click: ".sidebar-links > a" click: ".sidebar-links > a"

View file

@ -3,5 +3,6 @@ goto: file://|DOC_PATH|/lib2/struct.Foo.html
// We set a fixed size so there is no chance of "random" resize. // We set a fixed size so there is no chance of "random" resize.
size: (1100, 800) size: (1100, 800)
// We check that ".item-info" is bigger than its content. // We check that ".item-info" is bigger than its content.
assert-css: (".item-info", {"width": "757px"}) assert-css: (".item-info", {"width": "790px"})
assert-css: (".item-info .stab", {"width": "341px"}) assert-css: (".item-info .stab", {"width": "341px"})
assert-position: (".item-info .stab", {"x": 295})

View file

@ -0,0 +1,6 @@
struct X<const N: usize = {
(||1usize)()
//~^ ERROR calls in constants are limited to
}>;
fn main() {}

View file

@ -0,0 +1,9 @@
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
--> $DIR/issue-93647.rs:2:5
|
LL | (||1usize)()
| ^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0015`.

View file

@ -0,0 +1,10 @@
struct Foo<
'a,
const N: usize = {
let x: &'a ();
//~^ ERROR use of non-static lifetime `'a` in const generic
3
},
>(&'a ());
fn main() {}

View file

@ -0,0 +1,11 @@
error[E0771]: use of non-static lifetime `'a` in const generic
--> $DIR/outer-lifetime-in-const-generic-default.rs:4:17
|
LL | let x: &'a ();
| ^^
|
= note: for more information, see issue #74052 <https://github.com/rust-lang/rust/issues/74052>
error: aborting due to previous error
For more information about this error, try `rustc --explain E0771`.

View file

@ -17,6 +17,12 @@ error[E0604]: only `u8` can be cast as `char`, not `i8`
| |
LL | : [u32; 5i8 as char as usize] LL | : [u32; 5i8 as char as usize]
| ^^^^^^^^^^^ invalid cast | ^^^^^^^^^^^ invalid cast
|
help: try casting from `u8` instead
--> $DIR/const-eval-overflow-4b.rs:22:13
|
LL | : [u32; 5i8 as char as usize]
| ^^^^^^^^^^^
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -3,6 +3,12 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
| |
LL | 1u32 as char; LL | 1u32 as char;
| ^^^^^^^^^^^^ invalid cast | ^^^^^^^^^^^^ invalid cast
|
help: try `char::from_u32` instead
--> $DIR/E0604.rs:2:5
|
LL | 1u32 as char;
| ^^^^^^^^^^^^
error: aborting due to previous error error: aborting due to previous error

View file

@ -58,6 +58,12 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
| |
LL | 0u32 as char; LL | 0u32 as char;
| ^^^^^^^^^^^^ invalid cast | ^^^^^^^^^^^^ invalid cast
|
help: try `char::from_u32` instead
--> $DIR/error-festival.rs:25:5
|
LL | 0u32 as char;
| ^^^^^^^^^^^^
error[E0605]: non-primitive cast: `u8` as `Vec<u8>` error[E0605]: non-primitive cast: `u8` as `Vec<u8>`
--> $DIR/error-festival.rs:29:5 --> $DIR/error-festival.rs:29:5

View file

@ -315,17 +315,17 @@ fn test_expr() {
assert_eq!(stringify_expr!(mac! { ... }), "mac! { ... }"); assert_eq!(stringify_expr!(mac! { ... }), "mac! { ... }");
// ExprKind::Struct // ExprKind::Struct
assert_eq!(stringify_expr!(Struct {}), "Struct{}"); // FIXME assert_eq!(stringify_expr!(Struct {}), "Struct {}");
#[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5151 #[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5151
assert_eq!(stringify_expr!(<Struct as Trait>::Type {}), "<Struct as Trait>::Type{}"); assert_eq!(stringify_expr!(<Struct as Trait>::Type {}), "<Struct as Trait>::Type {}");
assert_eq!(stringify_expr!(Struct { .. }), "Struct{..}"); // FIXME assert_eq!(stringify_expr!(Struct { .. }), "Struct { .. }");
assert_eq!(stringify_expr!(Struct { ..base }), "Struct{..base}"); // FIXME assert_eq!(stringify_expr!(Struct { ..base }), "Struct { ..base }");
assert_eq!(stringify_expr!(Struct { x }), "Struct{x,}"); assert_eq!(stringify_expr!(Struct { x }), "Struct { x }");
assert_eq!(stringify_expr!(Struct { x, .. }), "Struct{x, ..}"); assert_eq!(stringify_expr!(Struct { x, .. }), "Struct { x, .. }");
assert_eq!(stringify_expr!(Struct { x, ..base }), "Struct{x, ..base}"); assert_eq!(stringify_expr!(Struct { x, ..base }), "Struct { x, ..base }");
assert_eq!(stringify_expr!(Struct { x: true }), "Struct{x: true,}"); assert_eq!(stringify_expr!(Struct { x: true }), "Struct { x: true }");
assert_eq!(stringify_expr!(Struct { x: true, .. }), "Struct{x: true, ..}"); assert_eq!(stringify_expr!(Struct { x: true, .. }), "Struct { x: true, .. }");
assert_eq!(stringify_expr!(Struct { x: true, ..base }), "Struct{x: true, ..base}"); assert_eq!(stringify_expr!(Struct { x: true, ..base }), "Struct { x: true, ..base }");
// ExprKind::Repeat // ExprKind::Repeat
assert_eq!(stringify_expr!([(); 0]), "[(); 0]"); assert_eq!(stringify_expr!([(); 0]), "[(); 0]");

View file

@ -99,6 +99,12 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
| |
LL | let _ = 0x61u32 as char; LL | let _ = 0x61u32 as char;
| ^^^^^^^^^^^^^^^ invalid cast | ^^^^^^^^^^^^^^^ invalid cast
|
help: try `char::from_u32` instead
--> $DIR/cast-rfc0401.rs:41:13
|
LL | let _ = 0x61u32 as char;
| ^^^^^^^^^^^^^^^
error[E0606]: casting `bool` as `f32` is invalid error[E0606]: casting `bool` as `f32` is invalid
--> $DIR/cast-rfc0401.rs:43:13 --> $DIR/cast-rfc0401.rs:43:13

View file

@ -0,0 +1,17 @@
// run-pass
// min-llvm-version: 13.0
// compiler-flags: -O
// Regression test for issue #80309
pub fn zero(x: usize) -> usize {
std::ptr::null::<i8>().wrapping_add(x) as usize - x
}
pub fn qux(x: &[i8]) -> i8 {
x[zero(x.as_ptr() as usize)]
}
fn main() {
let z = vec![42, 43];
println!("{}", qux(&z));
}

View file

@ -0,0 +1,14 @@
// run-pass
// min-llvm-version: 13.0
// compiler-flags: -O
// Regression test for issue #80309
pub unsafe fn foo(x: *const i8) -> i8 {
*x.wrapping_sub(x as _).wrapping_add(x as _)
}
fn main() {
let x = 42;
println!("{}", unsafe { foo(&x) });
}

View file

@ -1,6 +1,6 @@
[$DIR/dbg-macro-expected-behavior.rs:20] Unit = Unit [$DIR/dbg-macro-expected-behavior.rs:20] Unit = Unit
[$DIR/dbg-macro-expected-behavior.rs:21] a = Unit [$DIR/dbg-macro-expected-behavior.rs:21] a = Unit
[$DIR/dbg-macro-expected-behavior.rs:27] Point{x: 42, y: 24,} = Point { [$DIR/dbg-macro-expected-behavior.rs:27] Point { x: 42, y: 24 } = Point {
x: 42, x: 42,
y: 24, y: 24,
} }