mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-13 15:33:53 +00:00
Auto merge of #114024 - matthiaskrgr:rollup-uhdbq64, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #113969 (add dynamic for smir) - #113985 (Use erased self type when autoderefing for trait error suggestion) - #113987 (Comment stuff in the new solver) - #113992 (arm-none fixups) - #113993 (Optimize format usage) - #113994 (Optimize format usage) - #114006 (Update sparc-unknown-none-elf platform README) - #114021 (Add missing documentation for `Session::time`) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
fc8a3e357a
@ -420,13 +420,13 @@ impl Diagnostic {
|
|||||||
let expected_label = if expected_label.is_empty() {
|
let expected_label = if expected_label.is_empty() {
|
||||||
"expected".to_string()
|
"expected".to_string()
|
||||||
} else {
|
} else {
|
||||||
format!("expected {}", expected_label)
|
format!("expected {expected_label}")
|
||||||
};
|
};
|
||||||
let found_label = found_label.to_string();
|
let found_label = found_label.to_string();
|
||||||
let found_label = if found_label.is_empty() {
|
let found_label = if found_label.is_empty() {
|
||||||
"found".to_string()
|
"found".to_string()
|
||||||
} else {
|
} else {
|
||||||
format!("found {}", found_label)
|
format!("found {found_label}")
|
||||||
};
|
};
|
||||||
let (found_padding, expected_padding) = if expected_label.len() > found_label.len() {
|
let (found_padding, expected_padding) = if expected_label.len() > found_label.len() {
|
||||||
(expected_label.len() - found_label.len(), 0)
|
(expected_label.len() - found_label.len(), 0)
|
||||||
@ -439,13 +439,13 @@ impl Diagnostic {
|
|||||||
StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
|
StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
|
||||||
StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
|
StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
|
||||||
}));
|
}));
|
||||||
msg.push((format!("`{}\n", expected_extra), Style::NoStyle));
|
msg.push((format!("`{expected_extra}\n"), Style::NoStyle));
|
||||||
msg.push((format!("{}{} `", " ".repeat(found_padding), found_label), Style::NoStyle));
|
msg.push((format!("{}{} `", " ".repeat(found_padding), found_label), Style::NoStyle));
|
||||||
msg.extend(found.0.iter().map(|x| match *x {
|
msg.extend(found.0.iter().map(|x| match *x {
|
||||||
StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
|
StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
|
||||||
StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
|
StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
|
||||||
}));
|
}));
|
||||||
msg.push((format!("`{}", found_extra), Style::NoStyle));
|
msg.push((format!("`{found_extra}"), Style::NoStyle));
|
||||||
|
|
||||||
// For now, just attach these as notes.
|
// For now, just attach these as notes.
|
||||||
self.highlighted_note(msg);
|
self.highlighted_note(msg);
|
||||||
@ -454,7 +454,7 @@ impl Diagnostic {
|
|||||||
|
|
||||||
pub fn note_trait_signature(&mut self, name: Symbol, signature: String) -> &mut Self {
|
pub fn note_trait_signature(&mut self, name: Symbol, signature: String) -> &mut Self {
|
||||||
self.highlighted_note(vec![
|
self.highlighted_note(vec![
|
||||||
(format!("`{}` from trait: `", name), Style::NoStyle),
|
(format!("`{name}` from trait: `"), Style::NoStyle),
|
||||||
(signature, Style::Highlight),
|
(signature, Style::Highlight),
|
||||||
("`".to_string(), Style::NoStyle),
|
("`".to_string(), Style::NoStyle),
|
||||||
]);
|
]);
|
||||||
|
@ -102,7 +102,7 @@ impl IntoDiagnosticArg for bool {
|
|||||||
|
|
||||||
impl IntoDiagnosticArg for char {
|
impl IntoDiagnosticArg for char {
|
||||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||||
DiagnosticArgValue::Str(Cow::Owned(format!("{:?}", self)))
|
DiagnosticArgValue::Str(Cow::Owned(format!("{self:?}")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,12 +279,12 @@ pub trait Emitter: Translate {
|
|||||||
let msg = if substitution.is_empty() || sugg.style.hide_inline() {
|
let msg = if substitution.is_empty() || sugg.style.hide_inline() {
|
||||||
// This substitution is only removal OR we explicitly don't want to show the
|
// This substitution is only removal OR we explicitly don't want to show the
|
||||||
// code inline (`hide_inline`). Therefore, we don't show the substitution.
|
// code inline (`hide_inline`). Therefore, we don't show the substitution.
|
||||||
format!("help: {}", &msg)
|
format!("help: {msg}")
|
||||||
} else {
|
} else {
|
||||||
// Show the default suggestion text with the substitution
|
// Show the default suggestion text with the substitution
|
||||||
format!(
|
format!(
|
||||||
"help: {}{}: `{}`",
|
"help: {}{}: `{}`",
|
||||||
&msg,
|
msg,
|
||||||
if self.source_map().is_some_and(|sm| is_case_difference(
|
if self.source_map().is_some_and(|sm| is_case_difference(
|
||||||
sm,
|
sm,
|
||||||
substitution,
|
substitution,
|
||||||
|
@ -1485,7 +1485,7 @@ impl HandlerInner {
|
|||||||
let _ = self.fatal(errors);
|
let _ = self.fatal(errors);
|
||||||
}
|
}
|
||||||
(_, _) => {
|
(_, _) => {
|
||||||
let _ = self.fatal(format!("{}; {}", &errors, &warnings));
|
let _ = self.fatal(format!("{errors}; {warnings}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +238,7 @@ impl<'a> Parser<'a> {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
.into();
|
.into();
|
||||||
let invalid = format!("{}=", &sugg);
|
let invalid = format!("{sugg}=");
|
||||||
self.sess.emit_err(errors::InvalidComparisonOperator {
|
self.sess.emit_err(errors::InvalidComparisonOperator {
|
||||||
span: sp,
|
span: sp,
|
||||||
invalid: invalid.clone(),
|
invalid: invalid.clone(),
|
||||||
|
@ -157,15 +157,15 @@ fn emit_malformed_attribute(
|
|||||||
matches!(name, sym::doc | sym::ignore | sym::inline | sym::link | sym::test | sym::bench)
|
matches!(name, sym::doc | sym::ignore | sym::inline | sym::link | sym::test | sym::bench)
|
||||||
};
|
};
|
||||||
|
|
||||||
let error_msg = format!("malformed `{}` attribute input", name);
|
let error_msg = format!("malformed `{name}` attribute input");
|
||||||
let mut msg = "attribute must be of the form ".to_owned();
|
let mut msg = "attribute must be of the form ".to_owned();
|
||||||
let mut suggestions = vec![];
|
let mut suggestions = vec![];
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
let inner = if style == ast::AttrStyle::Inner { "!" } else { "" };
|
let inner = if style == ast::AttrStyle::Inner { "!" } else { "" };
|
||||||
if template.word {
|
if template.word {
|
||||||
first = false;
|
first = false;
|
||||||
let code = format!("#{}[{}]", inner, name);
|
let code = format!("#{inner}[{name}]");
|
||||||
msg.push_str(&format!("`{}`", &code));
|
msg.push_str(&format!("`{code}`"));
|
||||||
suggestions.push(code);
|
suggestions.push(code);
|
||||||
}
|
}
|
||||||
if let Some(descr) = template.list {
|
if let Some(descr) = template.list {
|
||||||
@ -173,16 +173,16 @@ fn emit_malformed_attribute(
|
|||||||
msg.push_str(" or ");
|
msg.push_str(" or ");
|
||||||
}
|
}
|
||||||
first = false;
|
first = false;
|
||||||
let code = format!("#{}[{}({})]", inner, name, descr);
|
let code = format!("#{inner}[{name}({descr})]");
|
||||||
msg.push_str(&format!("`{}`", &code));
|
msg.push_str(&format!("`{code}`"));
|
||||||
suggestions.push(code);
|
suggestions.push(code);
|
||||||
}
|
}
|
||||||
if let Some(descr) = template.name_value_str {
|
if let Some(descr) = template.name_value_str {
|
||||||
if !first {
|
if !first {
|
||||||
msg.push_str(" or ");
|
msg.push_str(" or ");
|
||||||
}
|
}
|
||||||
let code = format!("#{}[{} = \"{}\"]", inner, name, descr);
|
let code = format!("#{inner}[{name} = \"{descr}\"]");
|
||||||
msg.push_str(&format!("`{}`", &code));
|
msg.push_str(&format!("`{code}`"));
|
||||||
suggestions.push(code);
|
suggestions.push(code);
|
||||||
}
|
}
|
||||||
if should_warn(name) {
|
if should_warn(name) {
|
||||||
|
@ -7,6 +7,7 @@ impl Session {
|
|||||||
pub fn timer(&self, what: &'static str) -> VerboseTimingGuard<'_> {
|
pub fn timer(&self, what: &'static str) -> VerboseTimingGuard<'_> {
|
||||||
self.prof.verbose_generic_activity(what)
|
self.prof.verbose_generic_activity(what)
|
||||||
}
|
}
|
||||||
|
/// Used by `-Z self-profile`.
|
||||||
pub fn time<R>(&self, what: &'static str, f: impl FnOnce() -> R) -> R {
|
pub fn time<R>(&self, what: &'static str, f: impl FnOnce() -> R) -> R {
|
||||||
self.prof.verbose_generic_activity(what).run(f)
|
self.prof.verbose_generic_activity(what).run(f)
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,10 @@ pub fn br_named_def(did: DefId) -> stable_mir::ty::BrNamedDef {
|
|||||||
with_tables(|t| t.br_named_def(did))
|
with_tables(|t| t.br_named_def(did))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn trait_def(did: DefId) -> stable_mir::ty::TraitDef {
|
||||||
|
with_tables(|t| t.trait_def(did))
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> Tables<'tcx> {
|
impl<'tcx> Tables<'tcx> {
|
||||||
pub fn item_def_id(&self, item: &stable_mir::CrateItem) -> DefId {
|
pub fn item_def_id(&self, item: &stable_mir::CrateItem) -> DefId {
|
||||||
self.def_ids[item.0]
|
self.def_ids[item.0]
|
||||||
@ -100,6 +104,10 @@ impl<'tcx> Tables<'tcx> {
|
|||||||
stable_mir::ty::BrNamedDef(self.create_def_id(did))
|
stable_mir::ty::BrNamedDef(self.create_def_id(did))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn trait_def(&mut self, did: DefId) -> stable_mir::ty::TraitDef {
|
||||||
|
stable_mir::ty::TraitDef(self.create_def_id(did))
|
||||||
|
}
|
||||||
|
|
||||||
fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
|
fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
|
||||||
// FIXME: this becomes inefficient when we have too many ids
|
// FIXME: this becomes inefficient when we have too many ids
|
||||||
for (i, &d) in self.def_ids.iter().enumerate() {
|
for (i, &d) in self.def_ids.iter().enumerate() {
|
||||||
|
@ -258,6 +258,72 @@ impl<'tcx> Stable<'tcx> for ty::AliasTy<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::DynKind {
|
||||||
|
type T = stable_mir::ty::DynKind;
|
||||||
|
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use ty::DynKind;
|
||||||
|
match self {
|
||||||
|
DynKind::Dyn => stable_mir::ty::DynKind::Dyn,
|
||||||
|
DynKind::DynStar => stable_mir::ty::DynKind::DynStar,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::ExistentialPredicate<'tcx> {
|
||||||
|
type T = stable_mir::ty::ExistentialPredicate;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::ty::ExistentialPredicate::*;
|
||||||
|
match self {
|
||||||
|
ty::ExistentialPredicate::Trait(existential_trait_ref) => {
|
||||||
|
Trait(existential_trait_ref.stable(tables))
|
||||||
|
}
|
||||||
|
ty::ExistentialPredicate::Projection(existential_projection) => {
|
||||||
|
Projection(existential_projection.stable(tables))
|
||||||
|
}
|
||||||
|
ty::ExistentialPredicate::AutoTrait(def_id) => AutoTrait(tables.trait_def(*def_id)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::ExistentialTraitRef<'tcx> {
|
||||||
|
type T = stable_mir::ty::ExistentialTraitRef;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
let ty::ExistentialTraitRef { def_id, args } = self;
|
||||||
|
stable_mir::ty::ExistentialTraitRef {
|
||||||
|
def_id: tables.trait_def(*def_id),
|
||||||
|
generic_args: args.stable(tables),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::TermKind<'tcx> {
|
||||||
|
type T = stable_mir::ty::TermKind;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::ty::TermKind;
|
||||||
|
match self {
|
||||||
|
ty::TermKind::Ty(ty) => TermKind::Type(tables.intern_ty(*ty)),
|
||||||
|
ty::TermKind::Const(const_) => TermKind::Const(opaque(const_)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::ExistentialProjection<'tcx> {
|
||||||
|
type T = stable_mir::ty::ExistentialProjection;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
let ty::ExistentialProjection { def_id, args, term } = self;
|
||||||
|
stable_mir::ty::ExistentialProjection {
|
||||||
|
def_id: tables.trait_def(*def_id),
|
||||||
|
generic_args: args.stable(tables),
|
||||||
|
term: term.unpack().stable(tables),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion {
|
impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion {
|
||||||
type T = stable_mir::mir::PointerCoercion;
|
type T = stable_mir::mir::PointerCoercion;
|
||||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
@ -525,13 +591,17 @@ impl<'tcx> Stable<'tcx> for ty::GenericArgs<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Stable<'tcx> for ty::PolyFnSig<'tcx> {
|
impl<'tcx, S, V> Stable<'tcx> for ty::Binder<'tcx, S>
|
||||||
type T = stable_mir::ty::PolyFnSig;
|
where
|
||||||
|
S: Stable<'tcx, T = V>,
|
||||||
|
{
|
||||||
|
type T = stable_mir::ty::Binder<V>;
|
||||||
|
|
||||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
use stable_mir::ty::Binder;
|
use stable_mir::ty::Binder;
|
||||||
|
|
||||||
Binder {
|
Binder {
|
||||||
value: self.skip_binder().stable(tables),
|
value: self.as_ref().skip_binder().stable(tables),
|
||||||
bound_vars: self
|
bound_vars: self
|
||||||
.bound_vars()
|
.bound_vars()
|
||||||
.iter()
|
.iter()
|
||||||
@ -671,7 +741,16 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> {
|
|||||||
generic_args.stable(tables),
|
generic_args.stable(tables),
|
||||||
)),
|
)),
|
||||||
ty::FnPtr(poly_fn_sig) => TyKind::RigidTy(RigidTy::FnPtr(poly_fn_sig.stable(tables))),
|
ty::FnPtr(poly_fn_sig) => TyKind::RigidTy(RigidTy::FnPtr(poly_fn_sig.stable(tables))),
|
||||||
ty::Dynamic(_, _, _) => todo!(),
|
ty::Dynamic(existential_predicates, region, dyn_kind) => {
|
||||||
|
TyKind::RigidTy(RigidTy::Dynamic(
|
||||||
|
existential_predicates
|
||||||
|
.iter()
|
||||||
|
.map(|existential_predicate| existential_predicate.stable(tables))
|
||||||
|
.collect(),
|
||||||
|
opaque(region),
|
||||||
|
dyn_kind.stable(tables),
|
||||||
|
))
|
||||||
|
}
|
||||||
ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure(
|
ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure(
|
||||||
rustc_internal::closure_def(*def_id),
|
rustc_internal::closure_def(*def_id),
|
||||||
generic_args.stable(tables),
|
generic_args.stable(tables),
|
||||||
|
@ -38,6 +38,7 @@ pub enum RigidTy {
|
|||||||
FnPtr(PolyFnSig),
|
FnPtr(PolyFnSig),
|
||||||
Closure(ClosureDef, GenericArgs),
|
Closure(ClosureDef, GenericArgs),
|
||||||
Generator(GeneratorDef, GenericArgs, Movability),
|
Generator(GeneratorDef, GenericArgs, Movability),
|
||||||
|
Dynamic(Vec<Binder<ExistentialPredicate>>, Region, DynKind),
|
||||||
Never,
|
Never,
|
||||||
Tuple(Vec<Ty>),
|
Tuple(Vec<Ty>),
|
||||||
}
|
}
|
||||||
@ -98,6 +99,9 @@ pub struct AdtDef(pub(crate) DefId);
|
|||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub struct AliasDef(pub(crate) DefId);
|
pub struct AliasDef(pub(crate) DefId);
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
|
pub struct TraitDef(pub(crate) DefId);
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct GenericArgs(pub Vec<GenericArgKind>);
|
pub struct GenericArgs(pub Vec<GenericArgKind>);
|
||||||
|
|
||||||
@ -108,6 +112,12 @@ pub enum GenericArgKind {
|
|||||||
Const(Const),
|
Const(Const),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum TermKind {
|
||||||
|
Type(Ty),
|
||||||
|
Const(Const),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum AliasKind {
|
pub enum AliasKind {
|
||||||
Projection,
|
Projection,
|
||||||
@ -192,3 +202,29 @@ pub enum BoundRegionKind {
|
|||||||
BrNamed(BrNamedDef, String),
|
BrNamed(BrNamedDef, String),
|
||||||
BrEnv,
|
BrEnv,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum DynKind {
|
||||||
|
Dyn,
|
||||||
|
DynStar,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum ExistentialPredicate {
|
||||||
|
Trait(ExistentialTraitRef),
|
||||||
|
Projection(ExistentialProjection),
|
||||||
|
AutoTrait(TraitDef),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct ExistentialTraitRef {
|
||||||
|
pub def_id: TraitDef,
|
||||||
|
pub generic_args: GenericArgs,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct ExistentialProjection {
|
||||||
|
pub def_id: TraitDef,
|
||||||
|
pub generic_args: GenericArgs,
|
||||||
|
pub term: TermKind,
|
||||||
|
}
|
||||||
|
@ -5,7 +5,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
|
|||||||
|
|
||||||
pub fn target() -> Target {
|
pub fn target() -> Target {
|
||||||
Target {
|
Target {
|
||||||
llvm_target: "armebv7r-unknown-none-eabi".into(),
|
llvm_target: "armebv7r-none-eabi".into(),
|
||||||
pointer_width: 32,
|
pointer_width: 32,
|
||||||
data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
|
data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
|
||||||
arch: "arm".into(),
|
arch: "arm".into(),
|
||||||
@ -18,7 +18,7 @@ pub fn target() -> Target {
|
|||||||
panic_strategy: PanicStrategy::Abort,
|
panic_strategy: PanicStrategy::Abort,
|
||||||
max_atomic_width: Some(64),
|
max_atomic_width: Some(64),
|
||||||
emit_debug_gdb_scripts: false,
|
emit_debug_gdb_scripts: false,
|
||||||
// GCC and Clang default to 8 for arm-none here
|
// GCC defaults to 8 for arm-none here.
|
||||||
c_enum_min_bits: Some(8),
|
c_enum_min_bits: Some(8),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
@ -5,7 +5,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
|
|||||||
|
|
||||||
pub fn target() -> Target {
|
pub fn target() -> Target {
|
||||||
Target {
|
Target {
|
||||||
llvm_target: "armebv7r-unknown-none-eabihf".into(),
|
llvm_target: "armebv7r-none-eabihf".into(),
|
||||||
pointer_width: 32,
|
pointer_width: 32,
|
||||||
data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
|
data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
|
||||||
arch: "arm".into(),
|
arch: "arm".into(),
|
||||||
@ -19,7 +19,7 @@ pub fn target() -> Target {
|
|||||||
features: "+vfp3,-d32,-fp16".into(),
|
features: "+vfp3,-d32,-fp16".into(),
|
||||||
max_atomic_width: Some(64),
|
max_atomic_width: Some(64),
|
||||||
emit_debug_gdb_scripts: false,
|
emit_debug_gdb_scripts: false,
|
||||||
// GCC and Clang default to 8 for arm-none here
|
// GCC defaults to 8 for arm-none here.
|
||||||
c_enum_min_bits: Some(8),
|
c_enum_min_bits: Some(8),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
@ -39,9 +39,9 @@ pub fn target() -> Target {
|
|||||||
has_thumb_interworking: true,
|
has_thumb_interworking: true,
|
||||||
relocation_model: RelocModel::Static,
|
relocation_model: RelocModel::Static,
|
||||||
panic_strategy: PanicStrategy::Abort,
|
panic_strategy: PanicStrategy::Abort,
|
||||||
// from thumb_base, rust-lang/rust#44993.
|
// From thumb_base, rust-lang/rust#44993.
|
||||||
emit_debug_gdb_scripts: false,
|
emit_debug_gdb_scripts: false,
|
||||||
// from thumb_base, apparently gcc/clang give enums a minimum of 8 bits on no-os targets
|
// From thumb_base, GCC gives enums a minimum of 8 bits on no-os targets.
|
||||||
c_enum_min_bits: Some(8),
|
c_enum_min_bits: Some(8),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
@ -18,7 +18,7 @@ pub fn target() -> Target {
|
|||||||
max_atomic_width: Some(64),
|
max_atomic_width: Some(64),
|
||||||
panic_strategy: PanicStrategy::Abort,
|
panic_strategy: PanicStrategy::Abort,
|
||||||
emit_debug_gdb_scripts: false,
|
emit_debug_gdb_scripts: false,
|
||||||
// GCC and Clang default to 8 for arm-none here
|
// GCC defaults to 8 for arm-none here.
|
||||||
c_enum_min_bits: Some(8),
|
c_enum_min_bits: Some(8),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
|
|||||||
|
|
||||||
pub fn target() -> Target {
|
pub fn target() -> Target {
|
||||||
Target {
|
Target {
|
||||||
llvm_target: "armv7r-unknown-none-eabi".into(),
|
llvm_target: "armv7r-none-eabi".into(),
|
||||||
pointer_width: 32,
|
pointer_width: 32,
|
||||||
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
|
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
|
||||||
arch: "arm".into(),
|
arch: "arm".into(),
|
||||||
@ -17,7 +17,7 @@ pub fn target() -> Target {
|
|||||||
panic_strategy: PanicStrategy::Abort,
|
panic_strategy: PanicStrategy::Abort,
|
||||||
max_atomic_width: Some(64),
|
max_atomic_width: Some(64),
|
||||||
emit_debug_gdb_scripts: false,
|
emit_debug_gdb_scripts: false,
|
||||||
// GCC and Clang default to 8 for arm-none here
|
// GCC defaults to 8 for arm-none here.
|
||||||
c_enum_min_bits: Some(8),
|
c_enum_min_bits: Some(8),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
@ -4,7 +4,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
|
|||||||
|
|
||||||
pub fn target() -> Target {
|
pub fn target() -> Target {
|
||||||
Target {
|
Target {
|
||||||
llvm_target: "armv7r-unknown-none-eabihf".into(),
|
llvm_target: "armv7r-none-eabihf".into(),
|
||||||
pointer_width: 32,
|
pointer_width: 32,
|
||||||
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
|
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
|
||||||
arch: "arm".into(),
|
arch: "arm".into(),
|
||||||
@ -18,7 +18,7 @@ pub fn target() -> Target {
|
|||||||
features: "+vfp3,-d32,-fp16".into(),
|
features: "+vfp3,-d32,-fp16".into(),
|
||||||
max_atomic_width: Some(64),
|
max_atomic_width: Some(64),
|
||||||
emit_debug_gdb_scripts: false,
|
emit_debug_gdb_scripts: false,
|
||||||
// GCC and Clang default to 8 for arm-none here
|
// GCC defaults to 8 for arm-none here.
|
||||||
c_enum_min_bits: Some(8),
|
c_enum_min_bits: Some(8),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
@ -52,7 +52,7 @@ pub fn opts() -> TargetOptions {
|
|||||||
// breaks debugging. Preserve LR by default to prevent that from happening.
|
// breaks debugging. Preserve LR by default to prevent that from happening.
|
||||||
frame_pointer: FramePointer::Always,
|
frame_pointer: FramePointer::Always,
|
||||||
// ARM supports multiple ABIs for enums, the linux one matches the default of 32 here
|
// ARM supports multiple ABIs for enums, the linux one matches the default of 32 here
|
||||||
// but any arm-none or thumb-none target will be defaulted to 8 on GCC and clang
|
// but any arm-none or thumb-none target will be defaulted to 8 on GCC.
|
||||||
c_enum_min_bits: Some(8),
|
c_enum_min_bits: Some(8),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
|
@ -45,8 +45,6 @@ pub fn target() -> Target {
|
|||||||
relocation_model: RelocModel::Static,
|
relocation_model: RelocModel::Static,
|
||||||
// suggested from thumb_base, rust-lang/rust#44993.
|
// suggested from thumb_base, rust-lang/rust#44993.
|
||||||
emit_debug_gdb_scripts: false,
|
emit_debug_gdb_scripts: false,
|
||||||
// suggested from thumb_base, with no-os gcc/clang use 8-bit enums
|
|
||||||
c_enum_min_bits: Some(8),
|
|
||||||
frame_pointer: FramePointer::MayOmit,
|
frame_pointer: FramePointer::MayOmit,
|
||||||
|
|
||||||
main_needs_argc_argv: false,
|
main_needs_argc_argv: false,
|
||||||
|
@ -1,3 +1,16 @@
|
|||||||
|
//! Implements the `AliasRelate` goal, which is used when unifying aliases.
|
||||||
|
//! Doing this via a separate goal is called "deferred alias relation" and part
|
||||||
|
//! of our more general approach to "lazy normalization".
|
||||||
|
//!
|
||||||
|
//! This goal, e.g. `A alias-relate B`, may be satisfied by one of three branches:
|
||||||
|
//! * normalizes-to: If `A` is a projection, we can prove the equivalent
|
||||||
|
//! projection predicate with B as the right-hand side of the projection.
|
||||||
|
//! This goal is computed in both directions, if both are aliases.
|
||||||
|
//! * subst-relate: Equate `A` and `B` by their substs, if they're both
|
||||||
|
//! aliases with the same def-id.
|
||||||
|
//! * bidirectional-normalizes-to: If `A` and `B` are both projections, and both
|
||||||
|
//! may apply, then we can compute the "intersection" of both normalizes-to by
|
||||||
|
//! performing them together. This is used specifically to resolve ambiguities.
|
||||||
use super::{EvalCtxt, SolverMode};
|
use super::{EvalCtxt, SolverMode};
|
||||||
use rustc_infer::traits::query::NoSolution;
|
use rustc_infer::traits::query::NoSolution;
|
||||||
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
|
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
|
||||||
@ -118,6 +131,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Computes the normalizes-to branch, with side-effects. This must be performed
|
||||||
|
// in a probe in order to not taint the evaluation context.
|
||||||
fn normalizes_to_inner(
|
fn normalizes_to_inner(
|
||||||
&mut self,
|
&mut self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
@ -127,9 +142,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||||||
invert: Invert,
|
invert: Invert,
|
||||||
) -> Result<(), NoSolution> {
|
) -> Result<(), NoSolution> {
|
||||||
let other = match direction {
|
let other = match direction {
|
||||||
// This is purely an optimization.
|
// This is purely an optimization. No need to instantiate a new
|
||||||
|
// infer var and equate the RHS to it.
|
||||||
ty::AliasRelationDirection::Equate => other,
|
ty::AliasRelationDirection::Equate => other,
|
||||||
|
|
||||||
|
// Instantiate an infer var and subtype our RHS to it, so that we
|
||||||
|
// properly represent a subtype relation between the LHS and RHS
|
||||||
|
// of the goal.
|
||||||
ty::AliasRelationDirection::Subtype => {
|
ty::AliasRelationDirection::Subtype => {
|
||||||
let fresh = self.next_term_infer_of_kind(other);
|
let fresh = self.next_term_infer_of_kind(other);
|
||||||
let (sub, sup) = match invert {
|
let (sub, sup) = match invert {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//! Code which is used by built-in goals that match "structurally", such a auto
|
||||||
|
//! traits, `Copy`/`Clone`.
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_hir::{def_id::DefId, Movability, Mutability};
|
use rustc_hir::{def_id::DefId, Movability, Mutability};
|
||||||
use rustc_infer::traits::query::NoSolution;
|
use rustc_infer::traits::query::NoSolution;
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
/// Canonicalization is used to separate some goal from its context,
|
//! Canonicalization is used to separate some goal from its context,
|
||||||
/// throwing away unnecessary information in the process.
|
//! throwing away unnecessary information in the process.
|
||||||
///
|
//!
|
||||||
/// This is necessary to cache goals containing inference variables
|
//! This is necessary to cache goals containing inference variables
|
||||||
/// and placeholders without restricting them to the current `InferCtxt`.
|
//! and placeholders without restricting them to the current `InferCtxt`.
|
||||||
///
|
//!
|
||||||
/// Canonicalization is fairly involved, for more details see the relevant
|
//! Canonicalization is fairly involved, for more details see the relevant
|
||||||
/// section of the [rustc-dev-guide][c].
|
//! section of the [rustc-dev-guide][c].
|
||||||
///
|
//!
|
||||||
/// [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
|
//! [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
|
||||||
use super::{CanonicalInput, Certainty, EvalCtxt, Goal};
|
use super::{CanonicalInput, Certainty, EvalCtxt, Goal};
|
||||||
use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer};
|
use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer};
|
||||||
use crate::solve::{CanonicalResponse, QueryResult, Response};
|
use crate::solve::{CanonicalResponse, QueryResult, Response};
|
||||||
@ -135,6 +135,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Computes the region constraints and *new* opaque types registered when
|
||||||
|
/// proving a goal.
|
||||||
|
///
|
||||||
|
/// If an opaque was already constrained before proving this goal, then the
|
||||||
|
/// external constraints do not need to record that opaque, since if it is
|
||||||
|
/// further constrained by inference, that will be passed back in the var
|
||||||
|
/// values.
|
||||||
#[instrument(level = "debug", skip(self), ret)]
|
#[instrument(level = "debug", skip(self), ret)]
|
||||||
fn compute_external_query_constraints(&self) -> Result<ExternalConstraints<'tcx>, NoSolution> {
|
fn compute_external_query_constraints(&self) -> Result<ExternalConstraints<'tcx>, NoSolution> {
|
||||||
// We only check for leaks from universes which were entered inside
|
// We only check for leaks from universes which were entered inside
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
//! Computes a normalizes-to (projection) goal for inherent associated types,
|
||||||
|
//! `#![feature(inherent_associated_type)]`. Since astconv already determines
|
||||||
|
//! which impl the IAT is being projected from, we just:
|
||||||
|
//! 1. instantiate substs,
|
||||||
|
//! 2. equate the self type, and
|
||||||
|
//! 3. instantiate and register where clauses.
|
||||||
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
|
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
|
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
//! The new trait solver, currently still WIP.
|
//! The next-generation trait solver, currently still WIP.
|
||||||
//!
|
//!
|
||||||
//! As a user of the trait system, you can use `TyCtxt::evaluate_goal` to
|
//! As a user of rust, you can use `-Ztrait-solver=next` or `next-coherence`
|
||||||
//! interact with this solver.
|
//! to enable the new trait solver always, or just within coherence, respectively.
|
||||||
|
//!
|
||||||
|
//! As a developer of rustc, you shouldn't be using the new trait
|
||||||
|
//! solver without asking the trait-system-refactor-initiative, but it can
|
||||||
|
//! be enabled with `InferCtxtBuilder::with_next_trait_solver`. This will
|
||||||
|
//! ensure that trait solving using that inference context will be routed
|
||||||
|
//! to the new trait solver.
|
||||||
//!
|
//!
|
||||||
//! For a high-level overview of how this solver works, check out the relevant
|
//! For a high-level overview of how this solver works, check out the relevant
|
||||||
//! section of the rustc-dev-guide.
|
//! section of the rustc-dev-guide.
|
||||||
//!
|
//!
|
||||||
//! FIXME(@lcnr): Write that section. If you read this before then ask me
|
//! FIXME(@lcnr): Write that section. If you read this before then ask me
|
||||||
//! about it on zulip.
|
//! about it on zulip.
|
||||||
|
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
|
use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
|
||||||
use rustc_infer::traits::query::NoSolution;
|
use rustc_infer::traits::query::NoSolution;
|
||||||
|
@ -28,7 +28,8 @@ pub(crate) fn deeply_normalize<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
|
|||||||
/// its input to be already fully resolved.
|
/// its input to be already fully resolved.
|
||||||
///
|
///
|
||||||
/// Additionally takes a list of universes which represents the binders which have been
|
/// Additionally takes a list of universes which represents the binders which have been
|
||||||
/// entered before passing `value` to the function.
|
/// entered before passing `value` to the function. This is currently needed for
|
||||||
|
/// `normalize_erasing_regions`, which skips binders as it walks through a type.
|
||||||
pub(crate) fn deeply_normalize_with_skipped_universes<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
|
pub(crate) fn deeply_normalize_with_skipped_universes<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
|
||||||
at: At<'_, 'tcx>,
|
at: At<'_, 'tcx>,
|
||||||
value: T,
|
value: T,
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
//! Computes a normalizes-to (projection) goal for opaque types. This goal
|
||||||
|
//! behaves differently depending on the param-env's reveal mode and whether
|
||||||
|
//! the opaque is in a defining scope.
|
||||||
use rustc_middle::traits::query::NoSolution;
|
use rustc_middle::traits::query::NoSolution;
|
||||||
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
|
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
|
||||||
use rustc_middle::traits::Reveal;
|
use rustc_middle::traits::Reveal;
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
//! Computes a normalizes-to (projection) goal for inherent associated types,
|
||||||
|
//! `#![feature(lazy_type_alias)]` and `#![feature(type_alias_impl_trait)]`.
|
||||||
|
//!
|
||||||
|
//! Since a weak alias is not ambiguous, this just computes the `type_of` of
|
||||||
|
//! the alias and registers the where-clauses of the type alias.
|
||||||
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
|
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
|
|
||||||
|
@ -777,18 +777,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
real_trait_pred = parent_trait_pred;
|
real_trait_pred = parent_trait_pred;
|
||||||
}
|
}
|
||||||
|
|
||||||
let real_ty = real_trait_pred.self_ty();
|
|
||||||
// We `erase_late_bound_regions` here because `make_subregion` does not handle
|
// We `erase_late_bound_regions` here because `make_subregion` does not handle
|
||||||
// `ReLateBound`, and we don't particularly care about the regions.
|
// `ReLateBound`, and we don't particularly care about the regions.
|
||||||
if !self.can_eq(
|
let real_ty = self.tcx.erase_late_bound_regions(real_trait_pred.self_ty());
|
||||||
obligation.param_env,
|
if !self.can_eq(obligation.param_env, real_ty, arg_ty) {
|
||||||
self.tcx.erase_late_bound_regions(real_ty),
|
|
||||||
arg_ty,
|
|
||||||
) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let ty::Ref(region, base_ty, mutbl) = *real_ty.skip_binder().kind() {
|
if let ty::Ref(region, base_ty, mutbl) = *real_ty.kind() {
|
||||||
let autoderef = (self.autoderef_steps)(base_ty);
|
let autoderef = (self.autoderef_steps)(base_ty);
|
||||||
if let Some(steps) =
|
if let Some(steps) =
|
||||||
autoderef.into_iter().enumerate().find_map(|(steps, (ty, obligations))| {
|
autoderef.into_iter().enumerate().find_map(|(steps, (ty, obligations))| {
|
||||||
|
@ -17,13 +17,6 @@ Rust for bare-metal 32-bit SPARC V7 and V8 systems, e.g. the Gaisler LEON3.
|
|||||||
This target is cross-compiled. There is no support for `std`. There is no
|
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.
|
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;
|
By default, code generated with this target should run on any `SPARC` hardware;
|
||||||
enabling additional target features may raise this baseline.
|
enabling additional target features may raise this baseline.
|
||||||
|
|
||||||
@ -46,20 +39,31 @@ list in `config.toml`:
|
|||||||
```toml
|
```toml
|
||||||
[build]
|
[build]
|
||||||
build-stage = 1
|
build-stage = 1
|
||||||
target = ["sparc-unknown-none-elf"]
|
host = ["<target for your host>"]
|
||||||
|
target = ["<target for your host>", "sparc-unknown-none-elf"]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Replace `<target for your host>` with `x86_64-unknown-linux-gnu` or whatever
|
||||||
|
else is appropriate for your host machine.
|
||||||
|
|
||||||
## Building Rust programs
|
## Building Rust programs
|
||||||
|
|
||||||
```text
|
To build with this target, pass it to the `--target` argument, like:
|
||||||
|
|
||||||
|
```console
|
||||||
cargo build --target sparc-unknown-none-elf
|
cargo build --target sparc-unknown-none-elf
|
||||||
```
|
```
|
||||||
|
|
||||||
This target uses GCC as a linker, and so you will need an appropriate GCC
|
This target uses GCC as a linker, and so you will need an appropriate GCC
|
||||||
compatible `sparc-unknown-none` toolchain.
|
compatible `sparc-unknown-none` toolchain. The default linker binary is
|
||||||
|
`sparc-elf-gcc`, but you can override this in your project configuration, as
|
||||||
|
follows:
|
||||||
|
|
||||||
The default linker name is `sparc-elf-gcc`, but you can override this in your
|
`.cargo/config.toml`:
|
||||||
project configuration.
|
```toml
|
||||||
|
[target.sparc-unknown-none-elf]
|
||||||
|
linker = "sparc-custom-elf-gcc"
|
||||||
|
```
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
@ -81,6 +85,26 @@ something like:
|
|||||||
linker = "sparc-gaisler-elf-gcc"
|
linker = "sparc-gaisler-elf-gcc"
|
||||||
runner = "tsim-leon3"
|
runner = "tsim-leon3"
|
||||||
|
|
||||||
|
[build]
|
||||||
|
target = ["sparc-unknown-none-elf"]
|
||||||
|
rustflags = "-Ctarget-cpu=leon3"
|
||||||
|
```
|
||||||
|
|
||||||
|
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. The `libcore` was pre-compiled as part of the `rustc` compilation
|
||||||
|
process using the SPARC V7 baseline, but if you are using a nightly toolchain
|
||||||
|
you can use the
|
||||||
|
[`-Z build-std=core`](https://doc.rust-lang.org/cargo/reference/unstable.html#build-std)
|
||||||
|
option to rebuild `libcore` from source. This may be useful if you want to
|
||||||
|
compile it for SPARC V8 and take advantage of the extra instructions.
|
||||||
|
|
||||||
|
`.cargo/config.toml`:
|
||||||
|
```toml
|
||||||
|
[target.sparc-unknown-none-elf]
|
||||||
|
linker = "sparc-gaisler-elf-gcc"
|
||||||
|
runner = "tsim-leon3"
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
target = ["sparc-unknown-none-elf"]
|
target = ["sparc-unknown-none-elf"]
|
||||||
rustflags = "-Ctarget-cpu=leon3"
|
rustflags = "-Ctarget-cpu=leon3"
|
||||||
@ -89,16 +113,16 @@ rustflags = "-Ctarget-cpu=leon3"
|
|||||||
build-std = ["core"]
|
build-std = ["core"]
|
||||||
```
|
```
|
||||||
|
|
||||||
With this configuration, running `cargo run` will compile your code for the
|
Either way, once the simulator is running, simply enter the command `run` to
|
||||||
SPARC V8 compatible Gaisler Leon3 processor and then start the `tsim-leon3`
|
start the code executing in the simulator.
|
||||||
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]
|
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`
|
toolchain, and using its default Leon3 BSP, you can use call the C `putchar`
|
||||||
function and friends to output to the simulator console.
|
function and friends to output to the simulator console. The default linker
|
||||||
|
script is also appropriate for the Leon3 simulator, so no linker script is
|
||||||
|
required.
|
||||||
|
|
||||||
Here's a complete example:
|
Here's a complete example using the above config file:
|
||||||
|
|
||||||
```rust,ignore (cannot-test-this-because-it-assumes-special-libc-functions)
|
```rust,ignore (cannot-test-this-because-it-assumes-special-libc-functions)
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
22
tests/ui/traits/dont-autoderef-ty-with-escaping-var.rs
Normal file
22
tests/ui/traits/dont-autoderef-ty-with-escaping-var.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// issue:113951
|
||||||
|
|
||||||
|
trait Foo<'x, T> {}
|
||||||
|
|
||||||
|
trait RefFoo<T> {
|
||||||
|
fn ref_foo(&self);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> RefFoo<T> for T
|
||||||
|
where
|
||||||
|
for<'a> &'a mut Vec<&'a u32>: Foo<'static, T>,
|
||||||
|
{
|
||||||
|
fn ref_foo(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn coerce_lifetime2() {
|
||||||
|
<i32 as RefFoo<i32>>::ref_foo(unknown);
|
||||||
|
//~^ ERROR cannot find value `unknown` in this scope
|
||||||
|
//~| ERROR the trait bound `for<'a> &'a mut Vec<&'a u32>: Foo<'static, i32>` is not satisfied
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
27
tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr
Normal file
27
tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
error[E0425]: cannot find value `unknown` in this scope
|
||||||
|
--> $DIR/dont-autoderef-ty-with-escaping-var.rs:17:35
|
||||||
|
|
|
||||||
|
LL | <i32 as RefFoo<i32>>::ref_foo(unknown);
|
||||||
|
| ^^^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `for<'a> &'a mut Vec<&'a u32>: Foo<'static, i32>` is not satisfied
|
||||||
|
--> $DIR/dont-autoderef-ty-with-escaping-var.rs:17:35
|
||||||
|
|
|
||||||
|
LL | <i32 as RefFoo<i32>>::ref_foo(unknown);
|
||||||
|
| ----------------------------- ^^^^^^^ the trait `for<'a> Foo<'static, i32>` is not implemented for `&'a mut Vec<&'a u32>`
|
||||||
|
| |
|
||||||
|
| required by a bound introduced by this call
|
||||||
|
|
|
||||||
|
note: required for `i32` to implement `RefFoo<i32>`
|
||||||
|
--> $DIR/dont-autoderef-ty-with-escaping-var.rs:9:9
|
||||||
|
|
|
||||||
|
LL | impl<T> RefFoo<T> for T
|
||||||
|
| ^^^^^^^^^ ^
|
||||||
|
LL | where
|
||||||
|
LL | for<'a> &'a mut Vec<&'a u32>: Foo<'static, T>,
|
||||||
|
| --------------- unsatisfied trait bound introduced here
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0277, E0425.
|
||||||
|
For more information about an error, try `rustc --explain E0277`.
|
Loading…
Reference in New Issue
Block a user