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:
bors 2023-07-24 17:13:24 +00:00
commit fc8a3e357a
30 changed files with 315 additions and 76 deletions

View file

@ -420,13 +420,13 @@ impl Diagnostic {
let expected_label = if expected_label.is_empty() {
"expected".to_string()
} else {
format!("expected {}", expected_label)
format!("expected {expected_label}")
};
let found_label = found_label.to_string();
let found_label = if found_label.is_empty() {
"found".to_string()
} else {
format!("found {}", found_label)
format!("found {found_label}")
};
let (found_padding, expected_padding) = if expected_label.len() > found_label.len() {
(expected_label.len() - found_label.len(), 0)
@ -439,13 +439,13 @@ impl Diagnostic {
StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
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.extend(found.0.iter().map(|x| match *x {
StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
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.
self.highlighted_note(msg);
@ -454,7 +454,7 @@ impl Diagnostic {
pub fn note_trait_signature(&mut self, name: Symbol, signature: String) -> &mut Self {
self.highlighted_note(vec![
(format!("`{}` from trait: `", name), Style::NoStyle),
(format!("`{name}` from trait: `"), Style::NoStyle),
(signature, Style::Highlight),
("`".to_string(), Style::NoStyle),
]);

View file

@ -102,7 +102,7 @@ impl IntoDiagnosticArg for bool {
impl IntoDiagnosticArg for char {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
DiagnosticArgValue::Str(Cow::Owned(format!("{:?}", self)))
DiagnosticArgValue::Str(Cow::Owned(format!("{self:?}")))
}
}

View file

@ -279,12 +279,12 @@ pub trait Emitter: Translate {
let msg = if substitution.is_empty() || sugg.style.hide_inline() {
// 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.
format!("help: {}", &msg)
format!("help: {msg}")
} else {
// Show the default suggestion text with the substitution
format!(
"help: {}{}: `{}`",
&msg,
msg,
if self.source_map().is_some_and(|sm| is_case_difference(
sm,
substitution,

View file

@ -1485,7 +1485,7 @@ impl HandlerInner {
let _ = self.fatal(errors);
}
(_, _) => {
let _ = self.fatal(format!("{}; {}", &errors, &warnings));
let _ = self.fatal(format!("{errors}; {warnings}"));
}
}

View file

@ -238,7 +238,7 @@ impl<'a> Parser<'a> {
_ => unreachable!(),
}
.into();
let invalid = format!("{}=", &sugg);
let invalid = format!("{sugg}=");
self.sess.emit_err(errors::InvalidComparisonOperator {
span: sp,
invalid: invalid.clone(),

View file

@ -157,15 +157,15 @@ fn emit_malformed_attribute(
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 suggestions = vec![];
let mut first = true;
let inner = if style == ast::AttrStyle::Inner { "!" } else { "" };
if template.word {
first = false;
let code = format!("#{}[{}]", inner, name);
msg.push_str(&format!("`{}`", &code));
let code = format!("#{inner}[{name}]");
msg.push_str(&format!("`{code}`"));
suggestions.push(code);
}
if let Some(descr) = template.list {
@ -173,16 +173,16 @@ fn emit_malformed_attribute(
msg.push_str(" or ");
}
first = false;
let code = format!("#{}[{}({})]", inner, name, descr);
msg.push_str(&format!("`{}`", &code));
let code = format!("#{inner}[{name}({descr})]");
msg.push_str(&format!("`{code}`"));
suggestions.push(code);
}
if let Some(descr) = template.name_value_str {
if !first {
msg.push_str(" or ");
}
let code = format!("#{}[{} = \"{}\"]", inner, name, descr);
msg.push_str(&format!("`{}`", &code));
let code = format!("#{inner}[{name} = \"{descr}\"]");
msg.push_str(&format!("`{code}`"));
suggestions.push(code);
}
if should_warn(name) {

View file

@ -7,6 +7,7 @@ impl Session {
pub fn timer(&self, what: &'static str) -> VerboseTimingGuard<'_> {
self.prof.verbose_generic_activity(what)
}
/// Used by `-Z self-profile`.
pub fn time<R>(&self, what: &'static str, f: impl FnOnce() -> R) -> R {
self.prof.verbose_generic_activity(what).run(f)
}

View file

@ -59,6 +59,10 @@ pub fn br_named_def(did: DefId) -> stable_mir::ty::BrNamedDef {
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> {
pub fn item_def_id(&self, item: &stable_mir::CrateItem) -> DefId {
self.def_ids[item.0]
@ -100,6 +104,10 @@ impl<'tcx> Tables<'tcx> {
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 {
// FIXME: this becomes inefficient when we have too many ids
for (i, &d) in self.def_ids.iter().enumerate() {

View file

@ -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 {
type T = stable_mir::mir::PointerCoercion;
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> {
type T = stable_mir::ty::PolyFnSig;
impl<'tcx, S, V> Stable<'tcx> for ty::Binder<'tcx, S>
where
S: Stable<'tcx, T = V>,
{
type T = stable_mir::ty::Binder<V>;
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use stable_mir::ty::Binder;
Binder {
value: self.skip_binder().stable(tables),
value: self.as_ref().skip_binder().stable(tables),
bound_vars: self
.bound_vars()
.iter()
@ -671,7 +741,16 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> {
generic_args.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(
rustc_internal::closure_def(*def_id),
generic_args.stable(tables),

View file

@ -38,6 +38,7 @@ pub enum RigidTy {
FnPtr(PolyFnSig),
Closure(ClosureDef, GenericArgs),
Generator(GeneratorDef, GenericArgs, Movability),
Dynamic(Vec<Binder<ExistentialPredicate>>, Region, DynKind),
Never,
Tuple(Vec<Ty>),
}
@ -98,6 +99,9 @@ pub struct AdtDef(pub(crate) DefId);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct AliasDef(pub(crate) DefId);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct TraitDef(pub(crate) DefId);
#[derive(Clone, Debug)]
pub struct GenericArgs(pub Vec<GenericArgKind>);
@ -108,6 +112,12 @@ pub enum GenericArgKind {
Const(Const),
}
#[derive(Clone, Debug)]
pub enum TermKind {
Type(Ty),
Const(Const),
}
#[derive(Clone, Debug)]
pub enum AliasKind {
Projection,
@ -192,3 +202,29 @@ pub enum BoundRegionKind {
BrNamed(BrNamedDef, String),
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,
}

View file

@ -5,7 +5,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
pub fn target() -> Target {
Target {
llvm_target: "armebv7r-unknown-none-eabi".into(),
llvm_target: "armebv7r-none-eabi".into(),
pointer_width: 32,
data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
arch: "arm".into(),
@ -18,7 +18,7 @@ pub fn target() -> Target {
panic_strategy: PanicStrategy::Abort,
max_atomic_width: Some(64),
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),
..Default::default()
},

View file

@ -5,7 +5,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
pub fn target() -> Target {
Target {
llvm_target: "armebv7r-unknown-none-eabihf".into(),
llvm_target: "armebv7r-none-eabihf".into(),
pointer_width: 32,
data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
arch: "arm".into(),
@ -19,7 +19,7 @@ pub fn target() -> Target {
features: "+vfp3,-d32,-fp16".into(),
max_atomic_width: Some(64),
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),
..Default::default()
},

View file

@ -39,9 +39,9 @@ pub fn target() -> Target {
has_thumb_interworking: true,
relocation_model: RelocModel::Static,
panic_strategy: PanicStrategy::Abort,
// from thumb_base, rust-lang/rust#44993.
// From thumb_base, rust-lang/rust#44993.
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),
..Default::default()
},

View file

@ -18,7 +18,7 @@ pub fn target() -> Target {
max_atomic_width: Some(64),
panic_strategy: PanicStrategy::Abort,
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),
..Default::default()
};

View file

@ -4,7 +4,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
pub fn target() -> Target {
Target {
llvm_target: "armv7r-unknown-none-eabi".into(),
llvm_target: "armv7r-none-eabi".into(),
pointer_width: 32,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
arch: "arm".into(),
@ -17,7 +17,7 @@ pub fn target() -> Target {
panic_strategy: PanicStrategy::Abort,
max_atomic_width: Some(64),
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),
..Default::default()
},

View file

@ -4,7 +4,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
pub fn target() -> Target {
Target {
llvm_target: "armv7r-unknown-none-eabihf".into(),
llvm_target: "armv7r-none-eabihf".into(),
pointer_width: 32,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
arch: "arm".into(),
@ -18,7 +18,7 @@ pub fn target() -> Target {
features: "+vfp3,-d32,-fp16".into(),
max_atomic_width: Some(64),
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),
..Default::default()
},

View file

@ -52,7 +52,7 @@ pub fn opts() -> TargetOptions {
// breaks debugging. Preserve LR by default to prevent that from happening.
frame_pointer: FramePointer::Always,
// 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),
..Default::default()
}

View file

@ -45,8 +45,6 @@ pub fn target() -> Target {
relocation_model: RelocModel::Static,
// suggested from thumb_base, rust-lang/rust#44993.
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,
main_needs_argc_argv: false,

View file

@ -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 rustc_infer::traits::query::NoSolution;
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(
&mut self,
param_env: ty::ParamEnv<'tcx>,
@ -127,9 +142,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
invert: Invert,
) -> Result<(), NoSolution> {
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,
// 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 => {
let fresh = self.next_term_infer_of_kind(other);
let (sub, sup) = match invert {

View file

@ -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_hir::{def_id::DefId, Movability, Mutability};
use rustc_infer::traits::query::NoSolution;

View file

@ -1,13 +1,13 @@
/// Canonicalization is used to separate some goal from its context,
/// throwing away unnecessary information in the process.
///
/// This is necessary to cache goals containing inference variables
/// and placeholders without restricting them to the current `InferCtxt`.
///
/// Canonicalization is fairly involved, for more details see the relevant
/// section of the [rustc-dev-guide][c].
///
/// [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
//! Canonicalization is used to separate some goal from its context,
//! throwing away unnecessary information in the process.
//!
//! This is necessary to cache goals containing inference variables
//! and placeholders without restricting them to the current `InferCtxt`.
//!
//! Canonicalization is fairly involved, for more details see the relevant
//! section of the [rustc-dev-guide][c].
//!
//! [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
use super::{CanonicalInput, Certainty, EvalCtxt, Goal};
use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer};
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)]
fn compute_external_query_constraints(&self) -> Result<ExternalConstraints<'tcx>, NoSolution> {
// We only check for leaks from universes which were entered inside

View file

@ -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::ty;

View file

@ -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
//! interact with this solver.
//! As a user of rust, you can use `-Ztrait-solver=next` or `next-coherence`
//! 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
//! section of the rustc-dev-guide.
//!
//! FIXME(@lcnr): Write that section. If you read this before then ask me
//! about it on zulip.
use rustc_hir::def_id::DefId;
use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
use rustc_infer::traits::query::NoSolution;

View file

@ -28,7 +28,8 @@ pub(crate) fn deeply_normalize<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
/// its input to be already fully resolved.
///
/// 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>>>(
at: At<'_, 'tcx>,
value: T,

View file

@ -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::solve::{Certainty, Goal, QueryResult};
use rustc_middle::traits::Reveal;

View file

@ -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::ty;

View file

@ -777,18 +777,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
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
// `ReLateBound`, and we don't particularly care about the regions.
if !self.can_eq(
obligation.param_env,
self.tcx.erase_late_bound_regions(real_ty),
arg_ty,
) {
let real_ty = self.tcx.erase_late_bound_regions(real_trait_pred.self_ty());
if !self.can_eq(obligation.param_env, real_ty, arg_ty) {
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);
if let Some(steps) =
autoderef.into_iter().enumerate().find_map(|(steps, (ty, obligations))| {

View file

@ -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
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.
@ -46,20 +39,31 @@ list in `config.toml`:
```toml
[build]
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
```text
To build with this target, pass it to the `--target` argument, like:
```console
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.
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
project configuration.
`.cargo/config.toml`:
```toml
[target.sparc-unknown-none-elf]
linker = "sparc-custom-elf-gcc"
```
## Testing
@ -81,6 +85,26 @@ something like:
linker = "sparc-gaisler-elf-gcc"
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]
target = ["sparc-unknown-none-elf"]
rustflags = "-Ctarget-cpu=leon3"
@ -89,16 +113,16 @@ rustflags = "-Ctarget-cpu=leon3"
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.
Either way, 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.
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)
#![no_std]

View 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() {}

View 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`.