mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-18 09:53:26 +00:00
Auto merge of #113782 - matthiaskrgr:rollup-mmrjvx3, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #112741 (fix typo in `rustdoc/src/what-is-rustdoc.md`) - #113535 (Add a sparc-unknown-none-elf target.) - #113651 (self type param infer, avoid ICE) - #113770 (Generate safe stable code for derives on empty enums) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
1a8d09468f
@ -1134,9 +1134,14 @@ impl<'a> MethodDef<'a> {
|
||||
trait_: &TraitDef<'b>,
|
||||
enum_def: &'b EnumDef,
|
||||
type_ident: Ident,
|
||||
selflike_args: ThinVec<P<Expr>>,
|
||||
mut selflike_args: ThinVec<P<Expr>>,
|
||||
nonselflike_args: &[P<Expr>],
|
||||
) -> BlockOrExpr {
|
||||
assert!(
|
||||
!selflike_args.is_empty(),
|
||||
"static methods must use `expand_static_enum_method_body`",
|
||||
);
|
||||
|
||||
let span = trait_.span;
|
||||
let variants = &enum_def.variants;
|
||||
|
||||
@ -1144,10 +1149,15 @@ impl<'a> MethodDef<'a> {
|
||||
let unify_fieldless_variants =
|
||||
self.fieldless_variants_strategy == FieldlessVariantsStrategy::Unify;
|
||||
|
||||
// There is no sensible code to be generated for *any* deriving on a
|
||||
// zero-variant enum. So we just generate a failing expression.
|
||||
// For zero-variant enum, this function body is unreachable. Generate
|
||||
// `match *self {}`. This produces machine code identical to `unsafe {
|
||||
// core::intrinsics::unreachable() }` while being safe and stable.
|
||||
if variants.is_empty() {
|
||||
return BlockOrExpr(ThinVec::new(), Some(deriving::call_unreachable(cx, span)));
|
||||
selflike_args.truncate(1);
|
||||
let match_arg = cx.expr_deref(span, selflike_args.pop().unwrap());
|
||||
let match_arms = ThinVec::new();
|
||||
let expr = cx.expr_match(span, match_arg, match_arms);
|
||||
return BlockOrExpr(ThinVec::new(), Some(expr));
|
||||
}
|
||||
|
||||
let prefixes = iter::once("__self".to_string())
|
||||
|
@ -2,7 +2,7 @@ use crate::FnCtxt;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_infer::traits::ObligationCauseCode;
|
||||
use rustc_infer::{infer::type_variable::TypeVariableOriginKind, traits::ObligationCauseCode};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
|
||||
use rustc_span::{self, symbol::kw, Span};
|
||||
use rustc_trait_selection::traits;
|
||||
@ -267,8 +267,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
type BreakTy = ty::GenericArg<'tcx>;
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
|
||||
if let Some(origin) = self.0.type_var_origin(ty)
|
||||
&& let rustc_infer::infer::type_variable::TypeVariableOriginKind::TypeParameterDefinition(_, def_id) =
|
||||
origin.kind
|
||||
&& let TypeVariableOriginKind::TypeParameterDefinition(_, def_id) = origin.kind
|
||||
&& let generics = self.0.tcx.generics_of(self.1)
|
||||
&& let Some(index) = generics.param_def_id_to_index(self.0.tcx, def_id)
|
||||
&& let Some(subst) = ty::GenericArgs::identity_for_item(self.0.tcx, self.1)
|
||||
|
@ -163,7 +163,7 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte
|
||||
let ty_vars = infcx_inner.type_variables();
|
||||
let var_origin = ty_vars.var_origin(ty_vid);
|
||||
if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) = var_origin.kind
|
||||
&& !var_origin.span.from_expansion()
|
||||
&& name != kw::SelfUpper && !var_origin.span.from_expansion()
|
||||
{
|
||||
let generics = infcx.tcx.generics_of(infcx.tcx.parent(def_id));
|
||||
let idx = generics.param_def_id_to_index(infcx.tcx, def_id).unwrap();
|
||||
|
@ -1433,6 +1433,8 @@ supported_targets! {
|
||||
("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
|
||||
("riscv64gc-unknown-linux-musl", riscv64gc_unknown_linux_musl),
|
||||
|
||||
("sparc-unknown-none-elf", sparc_unknown_none_elf),
|
||||
|
||||
("loongarch64-unknown-none", loongarch64_unknown_none),
|
||||
("loongarch64-unknown-none-softfloat", loongarch64_unknown_none_softfloat),
|
||||
|
||||
|
27
compiler/rustc_target/src/spec/sparc_unknown_none_elf.rs
Normal file
27
compiler/rustc_target/src/spec/sparc_unknown_none_elf.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use crate::abi::Endian;
|
||||
use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let options = TargetOptions {
|
||||
linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No),
|
||||
linker: Some("sparc-elf-gcc".into()),
|
||||
endian: Endian::Big,
|
||||
cpu: "v7".into(),
|
||||
abi: "elf".into(),
|
||||
max_atomic_width: Some(32),
|
||||
atomic_cas: true,
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
relocation_model: RelocModel::Static,
|
||||
no_default_libraries: false,
|
||||
emit_debug_gdb_scripts: false,
|
||||
eh_frame_header: false,
|
||||
..Default::default()
|
||||
};
|
||||
Target {
|
||||
data_layout: "E-m:e-p:32:32-i64:64-f128:64-n32-S64".into(),
|
||||
llvm_target: "sparc-unknown-none-elf".into(),
|
||||
pointer_width: 32,
|
||||
arch: "sparc".into(),
|
||||
options,
|
||||
}
|
||||
}
|
@ -2388,14 +2388,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
// If there is only one implementation of the trait, suggest using it.
|
||||
// Otherwise, use a placeholder comment for the implementation.
|
||||
let (message, impl_suggestion) = if non_blanket_impl_count == 1 {(
|
||||
"use the fully-qualified path to the only available implementation".to_string(),
|
||||
"use the fully-qualified path to the only available implementation",
|
||||
format!("<{} as ", self.tcx.type_of(impl_def_id).instantiate_identity())
|
||||
)} else {(
|
||||
format!(
|
||||
"use a fully-qualified path to a specific available implementation ({} found)",
|
||||
non_blanket_impl_count
|
||||
),
|
||||
"</* self type */ as ".to_string()
|
||||
)} else {
|
||||
("use a fully-qualified path to a specific available implementation",
|
||||
"</* self type */ as ".to_string()
|
||||
)};
|
||||
let mut suggestions = vec![(
|
||||
path.span.shrink_to_lo(),
|
||||
|
@ -39,6 +39,7 @@
|
||||
- [mipsisa\*r6\*-unknown-linux-gnu\*](platform-support/mips-release-6.md)
|
||||
- [nvptx64-nvidia-cuda](platform-support/nvptx64-nvidia-cuda.md)
|
||||
- [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md)
|
||||
- [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
|
||||
- [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
|
||||
- [\*-nto-qnx-\*](platform-support/nto-qnx.md)
|
||||
- [\*-unknown-netbsd\*](platform-support/netbsd.md)
|
||||
|
@ -176,6 +176,7 @@ target | std | notes
|
||||
`thumbv8m.base-none-eabi` | * | Bare ARMv8-M Baseline
|
||||
`thumbv8m.main-none-eabi` | * | Bare ARMv8-M Mainline
|
||||
`thumbv8m.main-none-eabihf` | * | Bare ARMv8-M Mainline, hardfloat
|
||||
[`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | Bare 32-bit SPARC V7+
|
||||
`wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten
|
||||
`wasm32-unknown-unknown` | ✓ | WebAssembly
|
||||
`wasm32-wasi` | ✓ | WebAssembly with WASI
|
||||
|
164
src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md
Normal file
164
src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md
Normal file
@ -0,0 +1,164 @@
|
||||
# `sparc-unknown-none-elf`
|
||||
|
||||
**Tier: 3**
|
||||
|
||||
Rust for bare-metal 32-bit SPARC V7 and V8 systems, e.g. the Gaisler LEON3.
|
||||
|
||||
| Target | Descriptions |
|
||||
| ---------------------- | ----------------------------------------- |
|
||||
| sparc-unknown-none-elf | SPARC V7 32-bit (freestanding, hardfloat) |
|
||||
|
||||
## Target maintainers
|
||||
|
||||
- Jonathan Pallant, <jonathan.pallant@ferrous-systems.com>, https://ferrous-systems.com
|
||||
|
||||
## 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.
|
||||
|
||||
This allows the generated code to run in environments, such as kernels, which
|
||||
may need to avoid the use of such registers or which may have special
|
||||
considerations about the use of such registers (e.g. saving and restoring them
|
||||
to avoid breaking userspace code using the same registers). You can change code
|
||||
generation to use additional CPU features via the `-C target-feature=` codegen
|
||||
options to rustc, or via the `#[target_feature]` mechanism within Rust code.
|
||||
|
||||
By default, code generated with this target should run on any `SPARC` hardware;
|
||||
enabling additional target features may raise this baseline.
|
||||
|
||||
- `-Ctarget-cpu=v8` adds the extra SPARC V8 instructions.
|
||||
|
||||
- `-Ctarget-cpu=leon3` adds the SPARC V8 instructions and sets up scheduling to
|
||||
suit the Gaisler Leon3.
|
||||
|
||||
Functions marked `extern "C"` use the [standard SPARC architecture calling
|
||||
convention](https://sparc.org/technical-documents/).
|
||||
|
||||
This target generates ELF binaries. Any alternate formats or special
|
||||
considerations for binary layout will require linker options or linker scripts.
|
||||
|
||||
## Building the target
|
||||
|
||||
You can build Rust with support for the target by adding it to the `target`
|
||||
list in `config.toml`:
|
||||
|
||||
```toml
|
||||
[build]
|
||||
build-stage = 1
|
||||
target = ["sparc-unknown-none-elf"]
|
||||
```
|
||||
|
||||
## Building Rust programs
|
||||
|
||||
```text
|
||||
cargo build --target sparc-unknown-none-elf
|
||||
```
|
||||
|
||||
This target uses GCC as a linker, and so you will need an appropriate GCC
|
||||
compatible `sparc-unknown-none` toolchain.
|
||||
|
||||
The default linker name is `sparc-elf-gcc`, but you can override this in your
|
||||
project configuration.
|
||||
|
||||
## Testing
|
||||
|
||||
As `sparc-unknown-none-elf` supports a variety of different environments and does
|
||||
not support `std`, this target does not support running the Rust test suite.
|
||||
|
||||
## Cross-compilation toolchains and C code
|
||||
|
||||
This target was initially tested using [BCC2] from Gaisler, along with the TSIM
|
||||
Leon3 processor simulator. Both [BCC2] GCC and [BCC2] Clang have been shown to
|
||||
work. To work with these tools, your project configuration should contain
|
||||
something like:
|
||||
|
||||
[BCC2]: https://www.gaisler.com/index.php/downloads/compilers
|
||||
|
||||
`.cargo/config.toml`:
|
||||
```toml
|
||||
[target.sparc-unknown-none-elf]
|
||||
linker = "sparc-gaisler-elf-gcc"
|
||||
runner = "tsim-leon3"
|
||||
|
||||
[build]
|
||||
target = ["sparc-unknown-none-elf"]
|
||||
rustflags = "-Ctarget-cpu=leon3"
|
||||
|
||||
[unstable]
|
||||
build-std = ["core"]
|
||||
```
|
||||
|
||||
With this configuration, running `cargo run` will compile your code for the
|
||||
SPARC V8 compatible Gaisler Leon3 processor and then start the `tsim-leon3`
|
||||
simulator. Once the simulator is running, simply enter the command
|
||||
`run` to start the code executing in the simulator.
|
||||
|
||||
The default C toolchain libraries are linked in, so with the Gaisler [BCC2]
|
||||
toolchain, and using its default Leon3 BSP, you can use call the C `putchar`
|
||||
function and friends to output to the simulator console.
|
||||
|
||||
Here's a complete example:
|
||||
|
||||
```rust,ignore (cannot-test-this-because-it-assumes-special-libc-functions)
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
extern "C" {
|
||||
fn putchar(ch: i32);
|
||||
fn _exit(code: i32) -> !;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn main() -> i32 {
|
||||
let message = "Hello, this is Rust!";
|
||||
for b in message.bytes() {
|
||||
unsafe {
|
||||
putchar(b as i32);
|
||||
}
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(_panic: &core::panic::PanicInfo) -> ! {
|
||||
unsafe {
|
||||
_exit(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```console
|
||||
$ cargo run --target=sparc-unknown-none-elf
|
||||
Compiling sparc-demo-rust v0.1.0 (/work/sparc-demo-rust)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 3.44s
|
||||
Running `tsim-leon3 target/sparc-unknown-none-elf/debug/sparc-demo-rust`
|
||||
|
||||
TSIM3 LEON3 SPARC simulator, version 3.1.9 (evaluation version)
|
||||
|
||||
Copyright (C) 2023, Frontgrade Gaisler - all rights reserved.
|
||||
This software may only be used with a valid license.
|
||||
For latest updates, go to https://www.gaisler.com/
|
||||
Comments or bug-reports to support@gaisler.com
|
||||
|
||||
This TSIM evaluation version will expire 2023-11-28
|
||||
|
||||
Number of CPUs: 2
|
||||
system frequency: 50.000 MHz
|
||||
icache: 1 * 4 KiB, 16 bytes/line (4 KiB total)
|
||||
dcache: 1 * 4 KiB, 16 bytes/line (4 KiB total)
|
||||
Allocated 8192 KiB SRAM memory, in 1 bank at 0x40000000
|
||||
Allocated 32 MiB SDRAM memory, in 1 bank at 0x60000000
|
||||
Allocated 8192 KiB ROM memory at 0x00000000
|
||||
section: .text, addr: 0x40000000, size: 20528 bytes
|
||||
section: .rodata, addr: 0x40005030, size: 128 bytes
|
||||
section: .data, addr: 0x400050b0, size: 1176 bytes
|
||||
read 347 symbols
|
||||
|
||||
tsim> run
|
||||
Initializing and starting from 0x40000000
|
||||
Hello, this is Rust!
|
||||
|
||||
Program exited normally on CPU 0.
|
||||
tsim>
|
||||
```
|
@ -37,7 +37,7 @@ top, with no contents.
|
||||
## Configuring rustdoc
|
||||
|
||||
There are two problems with this: first, why does it
|
||||
think that our package is named "lib"? Second, why does it not have any
|
||||
think that our crate is named "lib"? Second, why does it not have any
|
||||
contents?
|
||||
|
||||
The first problem is due to `rustdoc` trying to be helpful; like `rustc`,
|
||||
|
@ -127,6 +127,7 @@ static TARGETS: &[&str] = &[
|
||||
"s390x-unknown-linux-gnu",
|
||||
"sparc64-unknown-linux-gnu",
|
||||
"sparcv9-sun-solaris",
|
||||
"sparc-unknown-none-elf",
|
||||
"thumbv6m-none-eabi",
|
||||
"thumbv7em-none-eabi",
|
||||
"thumbv7em-none-eabihf",
|
||||
|
@ -798,14 +798,14 @@ impl ::core::marker::Copy for Enum0 { }
|
||||
#[automatically_derived]
|
||||
impl ::core::fmt::Debug for Enum0 {
|
||||
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
||||
unsafe { ::core::intrinsics::unreachable() }
|
||||
match *self {}
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::hash::Hash for Enum0 {
|
||||
#[inline]
|
||||
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
|
||||
unsafe { ::core::intrinsics::unreachable() }
|
||||
match *self {}
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
@ -813,9 +813,7 @@ impl ::core::marker::StructuralPartialEq for Enum0 { }
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::PartialEq for Enum0 {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Enum0) -> bool {
|
||||
unsafe { ::core::intrinsics::unreachable() }
|
||||
}
|
||||
fn eq(&self, other: &Enum0) -> bool { match *self {} }
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::marker::StructuralEq for Enum0 { }
|
||||
@ -831,15 +829,13 @@ impl ::core::cmp::PartialOrd for Enum0 {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &Enum0)
|
||||
-> ::core::option::Option<::core::cmp::Ordering> {
|
||||
unsafe { ::core::intrinsics::unreachable() }
|
||||
match *self {}
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::Ord for Enum0 {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &Enum0) -> ::core::cmp::Ordering {
|
||||
unsafe { ::core::intrinsics::unreachable() }
|
||||
}
|
||||
fn cmp(&self, other: &Enum0) -> ::core::cmp::Ordering { match *self {} }
|
||||
}
|
||||
|
||||
// A single-variant enum.
|
||||
|
@ -7,7 +7,7 @@ LL | fn create() -> u32;
|
||||
LL | let cont: u32 = Generator::create();
|
||||
| ^^^^^^^^^^^^^^^^^ cannot call associated function of trait
|
||||
|
|
||||
help: use a fully-qualified path to a specific available implementation (2 found)
|
||||
help: use a fully-qualified path to a specific available implementation
|
||||
|
|
||||
LL | let cont: u32 = </* self type */ as Generator>::create();
|
||||
| +++++++++++++++++++ +
|
||||
|
@ -63,7 +63,7 @@ LL | fn my_fn();
|
||||
LL | MyTrait2::my_fn();
|
||||
| ^^^^^^^^^^^^^^^ cannot call associated function of trait
|
||||
|
|
||||
help: use a fully-qualified path to a specific available implementation (2 found)
|
||||
help: use a fully-qualified path to a specific available implementation
|
||||
|
|
||||
LL | </* self type */ as MyTrait2>::my_fn();
|
||||
| +++++++++++++++++++ +
|
||||
|
@ -0,0 +1,7 @@
|
||||
// Regression test for #113610 where we ICEd when trying to print
|
||||
// inference variables created by instantiating the self type parameter.
|
||||
|
||||
fn main() {
|
||||
let _ = (Default::default(),);
|
||||
//~^ ERROR cannot call associated function on trait
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
|
||||
--> $DIR/infer-var-for-self-param.rs:5:14
|
||||
|
|
||||
LL | let _ = (Default::default(),);
|
||||
| ^^^^^^^^^^^^^^^^ cannot call associated function of trait
|
||||
|
|
||||
help: use a fully-qualified path to a specific available implementation
|
||||
|
|
||||
LL | let _ = (</* self type */ as Default>::default(),);
|
||||
| +++++++++++++++++++ +
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0790`.
|
Loading…
Reference in New Issue
Block a user