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
30 changed files with 315 additions and 76 deletions
|
@ -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),
|
||||
]);
|
||||
|
|
|
@ -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:?}")))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1485,7 +1485,7 @@ impl HandlerInner {
|
|||
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!(),
|
||||
}
|
||||
.into();
|
||||
let invalid = format!("{}=", &sugg);
|
||||
let invalid = format!("{sugg}=");
|
||||
self.sess.emit_err(errors::InvalidComparisonOperator {
|
||||
span: sp,
|
||||
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)
|
||||
};
|
||||
|
||||
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) {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
},
|
||||
|
|
|
@ -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()
|
||||
},
|
||||
|
|
|
@ -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()
|
||||
},
|
||||
|
|
|
@ -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()
|
||||
};
|
||||
|
|
|
@ -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()
|
||||
},
|
||||
|
|
|
@ -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()
|
||||
},
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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))| {
|
||||
|
|
|
@ -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]
|
||||
|
|
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…
Add table
Reference in a new issue