mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 00:34:06 +00:00
Auto merge of #118763 - matthiaskrgr:rollup-mgyf5hp, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #117586 (Uplift the (new solver) canonicalizer into `rustc_next_trait_solver`) - #118502 (fix: correct the arg for 'suggest to use associated function syntax' diagnostic) - #118694 (Add instance evaluation and methods to read an allocation in StableMIR) - #118715 (privacy: visit trait def id of projections) - #118730 (recurse into refs when comparing tys for diagnostics) - #118736 (temporarily revert "ice on ambguity in mir typeck") r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
dc3a3539d5
@ -4303,6 +4303,13 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_next_trait_solver"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustc_type_ir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_parse"
|
||||
version = "0.0.0"
|
||||
@ -4487,6 +4494,7 @@ dependencies = [
|
||||
name = "rustc_smir"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustc_abi",
|
||||
"rustc_data_structures",
|
||||
"rustc_hir",
|
||||
"rustc_middle",
|
||||
@ -4571,6 +4579,7 @@ dependencies = [
|
||||
"rustc_infer",
|
||||
"rustc_macros",
|
||||
"rustc_middle",
|
||||
"rustc_next_trait_solver",
|
||||
"rustc_parse_format",
|
||||
"rustc_query_system",
|
||||
"rustc_session",
|
||||
|
@ -1591,10 +1591,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
{
|
||||
let sig = self.tcx.fn_sig(assoc.def_id).instantiate_identity();
|
||||
sig.inputs().skip_binder().get(0).and_then(|first| {
|
||||
if first.peel_refs() == rcvr_ty.peel_refs() {
|
||||
None
|
||||
} else {
|
||||
let impl_ty = self.tcx.type_of(*impl_did).instantiate_identity();
|
||||
// if the type of first arg is the same as the current impl type, we should take the first arg into assoc function
|
||||
if first.peel_refs() == impl_ty {
|
||||
Some(first.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
} else {
|
||||
|
@ -1181,37 +1181,54 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
debug!("cmp(t1={}, t1.kind={:?}, t2={}, t2.kind={:?})", t1, t1.kind(), t2, t2.kind());
|
||||
|
||||
// helper functions
|
||||
fn equals<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
|
||||
match (a.kind(), b.kind()) {
|
||||
(a, b) if *a == *b => true,
|
||||
(&ty::Int(_), &ty::Infer(ty::InferTy::IntVar(_)))
|
||||
| (
|
||||
&ty::Infer(ty::InferTy::IntVar(_)),
|
||||
&ty::Int(_) | &ty::Infer(ty::InferTy::IntVar(_)),
|
||||
)
|
||||
| (&ty::Float(_), &ty::Infer(ty::InferTy::FloatVar(_)))
|
||||
| (
|
||||
&ty::Infer(ty::InferTy::FloatVar(_)),
|
||||
&ty::Float(_) | &ty::Infer(ty::InferTy::FloatVar(_)),
|
||||
) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
let recurse = |t1, t2, values: &mut (DiagnosticStyledString, DiagnosticStyledString)| {
|
||||
let (x1, x2) = self.cmp(t1, t2);
|
||||
(values.0).0.extend(x1.0);
|
||||
(values.1).0.extend(x2.0);
|
||||
};
|
||||
|
||||
fn push_ty_ref<'tcx>(
|
||||
region: ty::Region<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
mutbl: hir::Mutability,
|
||||
s: &mut DiagnosticStyledString,
|
||||
) {
|
||||
fn fmt_region<'tcx>(region: ty::Region<'tcx>) -> String {
|
||||
let mut r = region.to_string();
|
||||
if r == "'_" {
|
||||
r.clear();
|
||||
} else {
|
||||
r.push(' ');
|
||||
}
|
||||
s.push_highlighted(format!("&{}{}", r, mutbl.prefix_str()));
|
||||
s.push_normal(ty.to_string());
|
||||
format!("&{r}")
|
||||
}
|
||||
|
||||
fn push_ref<'tcx>(
|
||||
region: ty::Region<'tcx>,
|
||||
mutbl: hir::Mutability,
|
||||
s: &mut DiagnosticStyledString,
|
||||
) {
|
||||
s.push_highlighted(fmt_region(region));
|
||||
s.push_highlighted(mutbl.prefix_str());
|
||||
}
|
||||
|
||||
fn cmp_ty_refs<'tcx>(
|
||||
r1: ty::Region<'tcx>,
|
||||
mut1: hir::Mutability,
|
||||
r2: ty::Region<'tcx>,
|
||||
mut2: hir::Mutability,
|
||||
ss: &mut (DiagnosticStyledString, DiagnosticStyledString),
|
||||
) {
|
||||
let (r1, r2) = (fmt_region(r1), fmt_region(r2));
|
||||
if r1 != r2 {
|
||||
ss.0.push_highlighted(r1);
|
||||
ss.1.push_highlighted(r2);
|
||||
} else {
|
||||
ss.0.push_normal(r1);
|
||||
ss.1.push_normal(r2);
|
||||
}
|
||||
|
||||
if mut1 != mut2 {
|
||||
ss.0.push_highlighted(mut1.prefix_str());
|
||||
ss.1.push_highlighted(mut2.prefix_str());
|
||||
} else {
|
||||
ss.0.push_normal(mut1.prefix_str());
|
||||
ss.1.push_normal(mut2.prefix_str());
|
||||
}
|
||||
}
|
||||
|
||||
// process starts here
|
||||
@ -1310,9 +1327,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
values.0.push_normal("_");
|
||||
values.1.push_normal("_");
|
||||
} else {
|
||||
let (x1, x2) = self.cmp(ta1, ta2);
|
||||
(values.0).0.extend(x1.0);
|
||||
(values.1).0.extend(x2.0);
|
||||
recurse(ta1, ta2, &mut values);
|
||||
}
|
||||
self.push_comma(&mut values.0, &mut values.1, len, i);
|
||||
}
|
||||
@ -1418,27 +1433,24 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
// When finding T != &T, highlight only the borrow
|
||||
(&ty::Ref(r1, ref_ty1, mutbl1), _) if equals(ref_ty1, t2) => {
|
||||
// When finding `&T != &T`, compare the references, then recurse into pointee type
|
||||
(&ty::Ref(r1, ref_ty1, mutbl1), &ty::Ref(r2, ref_ty2, mutbl2)) => {
|
||||
let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
|
||||
push_ty_ref(r1, ref_ty1, mutbl1, &mut values.0);
|
||||
values.1.push_normal(t2.to_string());
|
||||
cmp_ty_refs(r1, mutbl1, r2, mutbl2, &mut values);
|
||||
recurse(ref_ty1, ref_ty2, &mut values);
|
||||
values
|
||||
}
|
||||
(_, &ty::Ref(r2, ref_ty2, mutbl2)) if equals(t1, ref_ty2) => {
|
||||
// When finding T != &T, highlight the borrow
|
||||
(&ty::Ref(r1, ref_ty1, mutbl1), _) => {
|
||||
let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
|
||||
values.0.push_normal(t1.to_string());
|
||||
push_ty_ref(r2, ref_ty2, mutbl2, &mut values.1);
|
||||
push_ref(r1, mutbl1, &mut values.0);
|
||||
recurse(ref_ty1, t2, &mut values);
|
||||
values
|
||||
}
|
||||
|
||||
// When encountering &T != &mut T, highlight only the borrow
|
||||
(&ty::Ref(r1, ref_ty1, mutbl1), &ty::Ref(r2, ref_ty2, mutbl2))
|
||||
if equals(ref_ty1, ref_ty2) =>
|
||||
{
|
||||
(_, &ty::Ref(r2, ref_ty2, mutbl2)) => {
|
||||
let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
|
||||
push_ty_ref(r1, ref_ty1, mutbl1, &mut values.0);
|
||||
push_ty_ref(r2, ref_ty2, mutbl2, &mut values.1);
|
||||
push_ref(r2, mutbl2, &mut values.1);
|
||||
recurse(t1, ref_ty2, &mut values);
|
||||
values
|
||||
}
|
||||
|
||||
@ -1448,9 +1460,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
(DiagnosticStyledString::normal("("), DiagnosticStyledString::normal("("));
|
||||
let len = args1.len();
|
||||
for (i, (left, right)) in args1.iter().zip(args2).enumerate() {
|
||||
let (x1, x2) = self.cmp(left, right);
|
||||
(values.0).0.extend(x1.0);
|
||||
(values.1).0.extend(x2.0);
|
||||
recurse(left, right, &mut values);
|
||||
self.push_comma(&mut values.0, &mut values.1, len, i);
|
||||
}
|
||||
if len == 1 {
|
||||
|
@ -345,37 +345,61 @@ pub struct InferCtxt<'tcx> {
|
||||
impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
|
||||
type Interner = TyCtxt<'tcx>;
|
||||
|
||||
fn universe_of_ty(&self, ty: ty::InferTy) -> Option<ty::UniverseIndex> {
|
||||
use InferTy::*;
|
||||
match ty {
|
||||
// FIXME(BoxyUwU): this is kind of jank and means that printing unresolved
|
||||
// ty infers will give you the universe of the var it resolved to not the universe
|
||||
// it actually had. It also means that if you have a `?0.1` and infer it to `u8` then
|
||||
// try to print out `?0.1` it will just print `?0`.
|
||||
TyVar(ty_vid) => match self.probe_ty_var(ty_vid) {
|
||||
Err(universe) => Some(universe),
|
||||
Ok(_) => None,
|
||||
},
|
||||
IntVar(_) | FloatVar(_) | FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_) => None,
|
||||
fn interner(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn universe_of_ty(&self, vid: TyVid) -> Option<ty::UniverseIndex> {
|
||||
// FIXME(BoxyUwU): this is kind of jank and means that printing unresolved
|
||||
// ty infers will give you the universe of the var it resolved to not the universe
|
||||
// it actually had. It also means that if you have a `?0.1` and infer it to `u8` then
|
||||
// try to print out `?0.1` it will just print `?0`.
|
||||
match self.probe_ty_var(vid) {
|
||||
Err(universe) => Some(universe),
|
||||
Ok(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn universe_of_ct(&self, ct: ty::InferConst) -> Option<ty::UniverseIndex> {
|
||||
use ty::InferConst::*;
|
||||
match ct {
|
||||
// Same issue as with `universe_of_ty`
|
||||
Var(ct_vid) => match self.probe_const_var(ct_vid) {
|
||||
Err(universe) => Some(universe),
|
||||
Ok(_) => None,
|
||||
},
|
||||
EffectVar(_) => None,
|
||||
Fresh(_) => None,
|
||||
fn universe_of_ct(&self, ct: ConstVid) -> Option<ty::UniverseIndex> {
|
||||
// Same issue as with `universe_of_ty`
|
||||
match self.probe_const_var(ct) {
|
||||
Err(universe) => Some(universe),
|
||||
Ok(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex> {
|
||||
Some(self.universe_of_region_vid(lt))
|
||||
}
|
||||
|
||||
fn root_ty_var(&self, vid: TyVid) -> TyVid {
|
||||
self.root_var(vid)
|
||||
}
|
||||
|
||||
fn probe_ty_var(&self, vid: TyVid) -> Option<Ty<'tcx>> {
|
||||
self.probe_ty_var(vid).ok()
|
||||
}
|
||||
|
||||
fn root_lt_var(&self, vid: ty::RegionVid) -> ty::RegionVid {
|
||||
self.root_region_var(vid)
|
||||
}
|
||||
|
||||
fn probe_lt_var(&self, vid: ty::RegionVid) -> Option<ty::Region<'tcx>> {
|
||||
let re = self
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.unwrap_region_constraints()
|
||||
.opportunistic_resolve_var(self.tcx, vid);
|
||||
if re.is_var() { None } else { Some(re) }
|
||||
}
|
||||
|
||||
fn root_ct_var(&self, vid: ConstVid) -> ConstVid {
|
||||
self.root_const_var(vid)
|
||||
}
|
||||
|
||||
fn probe_ct_var(&self, vid: ConstVid) -> Option<ty::Const<'tcx>> {
|
||||
self.probe_const_var(vid).ok()
|
||||
}
|
||||
}
|
||||
|
||||
/// See the `error_reporting` module for more details.
|
||||
@ -1347,6 +1371,10 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
self.inner.borrow_mut().type_variables().root_var(var)
|
||||
}
|
||||
|
||||
pub fn root_region_var(&self, var: ty::RegionVid) -> ty::RegionVid {
|
||||
self.inner.borrow_mut().unwrap_region_constraints().root_var(var)
|
||||
}
|
||||
|
||||
pub fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid {
|
||||
self.inner.borrow_mut().const_unification_table().find(var).vid
|
||||
}
|
||||
|
@ -623,6 +623,11 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn root_var(&mut self, vid: ty::RegionVid) -> ty::RegionVid {
|
||||
let mut ut = self.unification_table_mut(); // FIXME(rust-lang/ena#42): unnecessary mut
|
||||
ut.find(vid).vid
|
||||
}
|
||||
|
||||
fn combine_map(&mut self, t: CombineMapType) -> &mut CombineMap<'tcx> {
|
||||
match t {
|
||||
Glb => &mut self.glbs,
|
||||
|
@ -7,7 +7,7 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_type_ir::{TypeFlags, WithCachedTypeInfo};
|
||||
use rustc_type_ir::{ConstTy, IntoKind, TypeFlags, WithCachedTypeInfo};
|
||||
|
||||
mod int;
|
||||
mod kind;
|
||||
@ -26,6 +26,20 @@ use super::sty::ConstKind;
|
||||
#[rustc_pass_by_value]
|
||||
pub struct Const<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo<ConstData<'tcx>>>);
|
||||
|
||||
impl<'tcx> IntoKind for Const<'tcx> {
|
||||
type Kind = ConstKind<'tcx>;
|
||||
|
||||
fn kind(self) -> ConstKind<'tcx> {
|
||||
self.kind().clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ConstTy<TyCtxt<'tcx>> for Const<'tcx> {
|
||||
fn ty(self) -> Ty<'tcx> {
|
||||
self.ty()
|
||||
}
|
||||
}
|
||||
|
||||
/// Typed constant value.
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, TyEncodable, TyDecodable)]
|
||||
pub struct ConstData<'tcx> {
|
||||
|
@ -133,6 +133,31 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||
) -> (Self::Ty, ty::Mutability) {
|
||||
(ty, mutbl)
|
||||
}
|
||||
|
||||
fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars {
|
||||
self.mk_canonical_var_infos(infos)
|
||||
}
|
||||
|
||||
fn mk_bound_ty(self, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self::Ty {
|
||||
Ty::new_bound(self, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon })
|
||||
}
|
||||
|
||||
fn mk_bound_region(self, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self::Region {
|
||||
Region::new_bound(
|
||||
self,
|
||||
debruijn,
|
||||
ty::BoundRegion { var, kind: ty::BoundRegionKind::BrAnon },
|
||||
)
|
||||
}
|
||||
|
||||
fn mk_bound_const(
|
||||
self,
|
||||
debruijn: ty::DebruijnIndex,
|
||||
var: ty::BoundVar,
|
||||
ty: Self::Ty,
|
||||
) -> Self::Const {
|
||||
Const::new_bound(self, debruijn, var, ty)
|
||||
}
|
||||
}
|
||||
|
||||
type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
|
||||
|
@ -65,15 +65,10 @@ use std::ops::ControlFlow;
|
||||
use std::{fmt, str};
|
||||
|
||||
pub use crate::ty::diagnostics::*;
|
||||
pub use rustc_type_ir::AliasKind::*;
|
||||
pub use rustc_type_ir::ConstKind::{
|
||||
Bound as BoundCt, Error as ErrorCt, Expr as ExprCt, Infer as InferCt, Param as ParamCt,
|
||||
Placeholder as PlaceholderCt, Unevaluated, Value,
|
||||
};
|
||||
pub use rustc_type_ir::DynKind::*;
|
||||
pub use rustc_type_ir::InferTy::*;
|
||||
pub use rustc_type_ir::RegionKind::*;
|
||||
pub use rustc_type_ir::TyKind::*;
|
||||
pub use rustc_type_ir::*;
|
||||
|
||||
pub use self::binding::BindingMode;
|
||||
@ -474,6 +469,14 @@ pub struct CReaderCacheKey {
|
||||
#[rustc_pass_by_value]
|
||||
pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>);
|
||||
|
||||
impl<'tcx> IntoKind for Ty<'tcx> {
|
||||
type Kind = TyKind<'tcx>;
|
||||
|
||||
fn kind(self) -> TyKind<'tcx> {
|
||||
self.kind().clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl EarlyParamRegion {
|
||||
/// Does this early bound region have a name? Early bound regions normally
|
||||
/// always have names except when using anonymous lifetimes (`'_`).
|
||||
@ -1545,34 +1548,42 @@ pub struct Placeholder<T> {
|
||||
|
||||
pub type PlaceholderRegion = Placeholder<BoundRegion>;
|
||||
|
||||
impl rustc_type_ir::Placeholder for PlaceholderRegion {
|
||||
fn universe(&self) -> UniverseIndex {
|
||||
impl PlaceholderLike for PlaceholderRegion {
|
||||
fn universe(self) -> UniverseIndex {
|
||||
self.universe
|
||||
}
|
||||
|
||||
fn var(&self) -> BoundVar {
|
||||
fn var(self) -> BoundVar {
|
||||
self.bound.var
|
||||
}
|
||||
|
||||
fn with_updated_universe(self, ui: UniverseIndex) -> Self {
|
||||
Placeholder { universe: ui, ..self }
|
||||
}
|
||||
|
||||
fn new(ui: UniverseIndex, var: BoundVar) -> Self {
|
||||
Placeholder { universe: ui, bound: BoundRegion { var, kind: BoundRegionKind::BrAnon } }
|
||||
}
|
||||
}
|
||||
|
||||
pub type PlaceholderType = Placeholder<BoundTy>;
|
||||
|
||||
impl rustc_type_ir::Placeholder for PlaceholderType {
|
||||
fn universe(&self) -> UniverseIndex {
|
||||
impl PlaceholderLike for PlaceholderType {
|
||||
fn universe(self) -> UniverseIndex {
|
||||
self.universe
|
||||
}
|
||||
|
||||
fn var(&self) -> BoundVar {
|
||||
fn var(self) -> BoundVar {
|
||||
self.bound.var
|
||||
}
|
||||
|
||||
fn with_updated_universe(self, ui: UniverseIndex) -> Self {
|
||||
Placeholder { universe: ui, ..self }
|
||||
}
|
||||
|
||||
fn new(ui: UniverseIndex, var: BoundVar) -> Self {
|
||||
Placeholder { universe: ui, bound: BoundTy { var, kind: BoundTyKind::Anon } }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
|
||||
@ -1584,18 +1595,22 @@ pub struct BoundConst<'tcx> {
|
||||
|
||||
pub type PlaceholderConst = Placeholder<BoundVar>;
|
||||
|
||||
impl rustc_type_ir::Placeholder for PlaceholderConst {
|
||||
fn universe(&self) -> UniverseIndex {
|
||||
impl PlaceholderLike for PlaceholderConst {
|
||||
fn universe(self) -> UniverseIndex {
|
||||
self.universe
|
||||
}
|
||||
|
||||
fn var(&self) -> BoundVar {
|
||||
fn var(self) -> BoundVar {
|
||||
self.bound
|
||||
}
|
||||
|
||||
fn with_updated_universe(self, ui: UniverseIndex) -> Self {
|
||||
Placeholder { universe: ui, ..self }
|
||||
}
|
||||
|
||||
fn new(ui: UniverseIndex, var: BoundVar) -> Self {
|
||||
Placeholder { universe: ui, bound: var }
|
||||
}
|
||||
}
|
||||
|
||||
/// When type checking, we use the `ParamEnv` to track
|
||||
|
@ -6,7 +6,7 @@ use crate::infer::canonical::Canonical;
|
||||
use crate::ty::visit::ValidateBoundVars;
|
||||
use crate::ty::InferTy::*;
|
||||
use crate::ty::{
|
||||
self, AdtDef, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable,
|
||||
self, AdtDef, Discr, IntoKind, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable,
|
||||
TypeVisitableExt, TypeVisitor,
|
||||
};
|
||||
use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
|
||||
@ -1477,6 +1477,14 @@ impl ParamConst {
|
||||
#[rustc_pass_by_value]
|
||||
pub struct Region<'tcx>(pub Interned<'tcx, RegionKind<'tcx>>);
|
||||
|
||||
impl<'tcx> IntoKind for Region<'tcx> {
|
||||
type Kind = RegionKind<'tcx>;
|
||||
|
||||
fn kind(self) -> RegionKind<'tcx> {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Region<'tcx> {
|
||||
#[inline]
|
||||
pub fn new_early_param(
|
||||
|
13
compiler/rustc_next_trait_solver/Cargo.toml
Normal file
13
compiler/rustc_next_trait_solver/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "rustc_next_trait_solver"
|
||||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
rustc_type_ir = { path = "../rustc_type_ir", default-features = false }
|
||||
|
||||
[features]
|
||||
default = ["nightly"]
|
||||
nightly = [
|
||||
"rustc_type_ir/nightly",
|
||||
]
|
@ -1,17 +1,10 @@
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use crate::infer::InferCtxt;
|
||||
use rustc_middle::infer::canonical::Canonical;
|
||||
use rustc_middle::infer::canonical::CanonicalTyVarKind;
|
||||
use rustc_middle::infer::canonical::CanonicalVarInfo;
|
||||
use rustc_middle::infer::canonical::CanonicalVarInfos;
|
||||
use rustc_middle::infer::canonical::CanonicalVarKind;
|
||||
use rustc_middle::ty::BoundRegionKind::BrAnon;
|
||||
use rustc_middle::ty::BoundTyKind;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_middle::ty::TypeVisitableExt;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_middle::ty::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
||||
use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
||||
use rustc_type_ir::{
|
||||
self as ty, Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, ConstTy,
|
||||
InferCtxtLike, Interner, IntoKind, PlaceholderLike,
|
||||
};
|
||||
|
||||
/// Whether we're canonicalizing a query input or the query response.
|
||||
///
|
||||
@ -42,23 +35,22 @@ pub enum CanonicalizeMode {
|
||||
},
|
||||
}
|
||||
|
||||
pub struct Canonicalizer<'a, 'tcx> {
|
||||
infcx: &'a InferCtxt<'tcx>,
|
||||
pub struct Canonicalizer<'a, Infcx: InferCtxtLike<Interner = I>, I: Interner> {
|
||||
infcx: &'a Infcx,
|
||||
canonicalize_mode: CanonicalizeMode,
|
||||
|
||||
variables: &'a mut Vec<ty::GenericArg<'tcx>>,
|
||||
primitive_var_infos: Vec<CanonicalVarInfo<'tcx>>,
|
||||
variables: &'a mut Vec<I::GenericArg>,
|
||||
primitive_var_infos: Vec<CanonicalVarInfo<I>>,
|
||||
binder_index: ty::DebruijnIndex,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Canonicalizer<'a, 'tcx> {
|
||||
#[instrument(level = "debug", skip(infcx), ret)]
|
||||
pub fn canonicalize<T: TypeFoldable<TyCtxt<'tcx>>>(
|
||||
infcx: &'a InferCtxt<'tcx>,
|
||||
impl<'a, Infcx: InferCtxtLike<Interner = I>, I: Interner> Canonicalizer<'a, Infcx, I> {
|
||||
pub fn canonicalize<T: TypeFoldable<I>>(
|
||||
infcx: &'a Infcx,
|
||||
canonicalize_mode: CanonicalizeMode,
|
||||
variables: &'a mut Vec<ty::GenericArg<'tcx>>,
|
||||
variables: &'a mut Vec<I::GenericArg>,
|
||||
value: T,
|
||||
) -> Canonical<'tcx, T> {
|
||||
) -> ty::Canonical<I, T> {
|
||||
let mut canonicalizer = Canonicalizer {
|
||||
infcx,
|
||||
canonicalize_mode,
|
||||
@ -69,15 +61,16 @@ impl<'a, 'tcx> Canonicalizer<'a, 'tcx> {
|
||||
};
|
||||
|
||||
let value = value.fold_with(&mut canonicalizer);
|
||||
assert!(!value.has_infer(), "unexpected infer in {value:?}");
|
||||
assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}");
|
||||
// FIXME: Restore these assertions. Should we uplift type flags?
|
||||
// assert!(!value.has_infer(), "unexpected infer in {value:?}");
|
||||
// assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}");
|
||||
|
||||
let (max_universe, variables) = canonicalizer.finalize();
|
||||
|
||||
Canonical { max_universe, variables, value }
|
||||
}
|
||||
|
||||
fn finalize(self) -> (ty::UniverseIndex, CanonicalVarInfos<'tcx>) {
|
||||
fn finalize(self) -> (ty::UniverseIndex, I::CanonicalVars) {
|
||||
let mut var_infos = self.primitive_var_infos;
|
||||
// See the rustc-dev-guide section about how we deal with universes
|
||||
// during canonicalization in the new solver.
|
||||
@ -105,7 +98,7 @@ impl<'a, 'tcx> Canonicalizer<'a, 'tcx> {
|
||||
.max()
|
||||
.unwrap_or(ty::UniverseIndex::ROOT);
|
||||
|
||||
let var_infos = self.infcx.tcx.mk_canonical_var_infos(&var_infos);
|
||||
let var_infos = self.infcx.interner().mk_canonical_var_infos(&var_infos);
|
||||
return (max_universe, var_infos);
|
||||
}
|
||||
}
|
||||
@ -131,7 +124,7 @@ impl<'a, 'tcx> Canonicalizer<'a, 'tcx> {
|
||||
let mut existential_in_new_uv = false;
|
||||
let mut next_orig_uv = Some(ty::UniverseIndex::ROOT);
|
||||
while let Some(orig_uv) = next_orig_uv.take() {
|
||||
let mut update_uv = |var: &mut CanonicalVarInfo<'tcx>, orig_uv, is_existential| {
|
||||
let mut update_uv = |var: &mut CanonicalVarInfo<I>, orig_uv, is_existential| {
|
||||
let uv = var.universe();
|
||||
match uv.cmp(&orig_uv) {
|
||||
Ordering::Less => (), // Already updated
|
||||
@ -187,19 +180,22 @@ impl<'a, 'tcx> Canonicalizer<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
let var_infos = self.infcx.tcx.mk_canonical_var_infos(&var_infos);
|
||||
let var_infos = self.infcx.interner().mk_canonical_var_infos(&var_infos);
|
||||
(curr_compressed_uv, var_infos)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
|
||||
fn interner(&self) -> TyCtxt<'tcx> {
|
||||
self.infcx.tcx
|
||||
impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
|
||||
for Canonicalizer<'_, Infcx, I>
|
||||
{
|
||||
fn interner(&self) -> I {
|
||||
self.infcx.interner()
|
||||
}
|
||||
|
||||
fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
|
||||
fn fold_binder<T>(&mut self, t: I::Binder<T>) -> I::Binder<T>
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
T: TypeFoldable<I>,
|
||||
I::Binder<T>: TypeSuperFoldable<I>,
|
||||
{
|
||||
self.binder_index.shift_in(1);
|
||||
let t = t.super_fold_with(self);
|
||||
@ -207,21 +203,8 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
|
||||
t
|
||||
}
|
||||
|
||||
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
|
||||
if let ty::ReVar(vid) = *r {
|
||||
let resolved_region = self
|
||||
.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.unwrap_region_constraints()
|
||||
.opportunistic_resolve_var(self.infcx.tcx, vid);
|
||||
assert_eq!(
|
||||
r, resolved_region,
|
||||
"region var should have been resolved, {r} -> {resolved_region}"
|
||||
);
|
||||
}
|
||||
|
||||
let kind = match *r {
|
||||
fn fold_region(&mut self, r: I::Region) -> I::Region {
|
||||
let kind = match r.kind() {
|
||||
ty::ReBound(..) => return r,
|
||||
|
||||
// We may encounter `ReStatic` in item signatures or the hidden type
|
||||
@ -237,9 +220,11 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
|
||||
CanonicalizeMode::Response { .. } => return r,
|
||||
},
|
||||
|
||||
ty::ReLateParam(_) | ty::ReEarlyParam(_) => match self.canonicalize_mode {
|
||||
ty::ReEarlyParam(_) | ty::ReLateParam(_) => match self.canonicalize_mode {
|
||||
CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
|
||||
CanonicalizeMode::Response { .. } => bug!("unexpected region in response: {r:?}"),
|
||||
CanonicalizeMode::Response { .. } => {
|
||||
panic!("unexpected region in response: {r:?}")
|
||||
}
|
||||
},
|
||||
|
||||
ty::RePlaceholder(placeholder) => match self.canonicalize_mode {
|
||||
@ -248,20 +233,32 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
|
||||
CanonicalizeMode::Response { max_input_universe } => {
|
||||
// If we have a placeholder region inside of a query, it must be from
|
||||
// a new universe.
|
||||
if max_input_universe.can_name(placeholder.universe) {
|
||||
bug!("new placeholder in universe {max_input_universe:?}: {r:?}");
|
||||
if max_input_universe.can_name(placeholder.universe()) {
|
||||
panic!("new placeholder in universe {max_input_universe:?}: {r:?}");
|
||||
}
|
||||
CanonicalVarKind::PlaceholderRegion(placeholder)
|
||||
}
|
||||
},
|
||||
|
||||
ty::ReVar(_) => match self.canonicalize_mode {
|
||||
CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
|
||||
CanonicalizeMode::Response { .. } => {
|
||||
CanonicalVarKind::Region(self.infcx.universe_of_region(r))
|
||||
}
|
||||
},
|
||||
ty::ReVar(vid) => {
|
||||
assert_eq!(
|
||||
self.infcx.root_lt_var(vid),
|
||||
vid,
|
||||
"region vid should have been resolved fully before canonicalization"
|
||||
);
|
||||
assert_eq!(
|
||||
self.infcx.probe_lt_var(vid),
|
||||
None,
|
||||
"region vid should have been resolved fully before canonicalization"
|
||||
);
|
||||
|
||||
match self.canonicalize_mode {
|
||||
CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
|
||||
CanonicalizeMode::Response { .. } => {
|
||||
CanonicalVarKind::Region(self.infcx.universe_of_lt(vid).unwrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::ReError(_) => return r,
|
||||
};
|
||||
|
||||
@ -271,55 +268,60 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
|
||||
self.variables.iter().position(|&v| v == r.into()).map(ty::BoundVar::from)
|
||||
}
|
||||
};
|
||||
|
||||
let var = existing_bound_var.unwrap_or_else(|| {
|
||||
let var = ty::BoundVar::from(self.variables.len());
|
||||
self.variables.push(r.into());
|
||||
self.primitive_var_infos.push(CanonicalVarInfo { kind });
|
||||
var
|
||||
});
|
||||
let br = ty::BoundRegion { var, kind: BrAnon };
|
||||
ty::Region::new_bound(self.interner(), self.binder_index, br)
|
||||
|
||||
self.interner().mk_bound_region(self.binder_index, var)
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let kind = match *t.kind() {
|
||||
ty::Infer(ty::TyVar(vid)) => {
|
||||
assert_eq!(self.infcx.root_var(vid), vid, "ty vid should have been resolved");
|
||||
let Err(ui) = self.infcx.probe_ty_var(vid) else {
|
||||
bug!("ty var should have been resolved: {t}");
|
||||
};
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
|
||||
}
|
||||
ty::Infer(ty::IntVar(vid)) => {
|
||||
assert_eq!(self.infcx.opportunistic_resolve_int_var(vid), t);
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
|
||||
}
|
||||
ty::Infer(ty::FloatVar(vid)) => {
|
||||
assert_eq!(self.infcx.opportunistic_resolve_float_var(vid), t);
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::Float)
|
||||
}
|
||||
ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
||||
bug!("fresh var during canonicalization: {t:?}")
|
||||
}
|
||||
fn fold_ty(&mut self, t: I::Ty) -> I::Ty
|
||||
where
|
||||
I::Ty: TypeSuperFoldable<I>,
|
||||
{
|
||||
let kind = match t.kind() {
|
||||
ty::Infer(i) => match i {
|
||||
ty::TyVar(vid) => {
|
||||
assert_eq!(
|
||||
self.infcx.root_ty_var(vid),
|
||||
vid,
|
||||
"ty vid should have been resolved fully before canonicalization"
|
||||
);
|
||||
assert_eq!(
|
||||
self.infcx.probe_ty_var(vid),
|
||||
None,
|
||||
"ty vid should have been resolved fully before canonicalization"
|
||||
);
|
||||
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(
|
||||
self.infcx
|
||||
.universe_of_ty(vid)
|
||||
.unwrap_or_else(|| panic!("ty var should have been resolved: {t:?}")),
|
||||
))
|
||||
}
|
||||
ty::IntVar(_) => CanonicalVarKind::Ty(CanonicalTyVarKind::Int),
|
||||
ty::FloatVar(_) => CanonicalVarKind::Ty(CanonicalTyVarKind::Float),
|
||||
ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {
|
||||
todo!()
|
||||
}
|
||||
},
|
||||
ty::Placeholder(placeholder) => match self.canonicalize_mode {
|
||||
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(ty::Placeholder {
|
||||
universe: placeholder.universe,
|
||||
bound: ty::BoundTy {
|
||||
var: ty::BoundVar::from_usize(self.variables.len()),
|
||||
kind: ty::BoundTyKind::Anon,
|
||||
},
|
||||
}),
|
||||
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(PlaceholderLike::new(
|
||||
placeholder.universe(),
|
||||
self.variables.len().into(),
|
||||
)),
|
||||
CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder),
|
||||
},
|
||||
ty::Param(_) => match self.canonicalize_mode {
|
||||
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(ty::Placeholder {
|
||||
universe: ty::UniverseIndex::ROOT,
|
||||
bound: ty::BoundTy {
|
||||
var: ty::BoundVar::from_usize(self.variables.len()),
|
||||
kind: ty::BoundTyKind::Anon,
|
||||
},
|
||||
}),
|
||||
CanonicalizeMode::Response { .. } => bug!("param ty in response: {t:?}"),
|
||||
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(PlaceholderLike::new(
|
||||
ty::UniverseIndex::ROOT,
|
||||
self.variables.len().into(),
|
||||
)),
|
||||
CanonicalizeMode::Response { .. } => panic!("param ty in response: {t:?}"),
|
||||
},
|
||||
ty::Bool
|
||||
| ty::Char
|
||||
@ -354,44 +356,38 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
|
||||
var
|
||||
}),
|
||||
);
|
||||
let bt = ty::BoundTy { var, kind: BoundTyKind::Anon };
|
||||
Ty::new_bound(self.infcx.tcx, self.binder_index, bt)
|
||||
|
||||
self.interner().mk_bound_ty(self.binder_index, var)
|
||||
}
|
||||
|
||||
fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||
fn fold_const(&mut self, c: I::Const) -> I::Const
|
||||
where
|
||||
I::Const: TypeSuperFoldable<I>,
|
||||
{
|
||||
let kind = match c.kind() {
|
||||
ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
|
||||
assert_eq!(
|
||||
self.infcx.root_const_var(vid),
|
||||
vid,
|
||||
"const var should have been resolved"
|
||||
);
|
||||
let Err(ui) = self.infcx.probe_const_var(vid) else {
|
||||
bug!("const var should have been resolved");
|
||||
};
|
||||
// FIXME: we should fold this ty eventually
|
||||
CanonicalVarKind::Const(ui, c.ty())
|
||||
}
|
||||
ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => {
|
||||
assert_eq!(
|
||||
self.infcx.root_effect_var(vid),
|
||||
vid,
|
||||
"effect var should have been resolved"
|
||||
);
|
||||
let None = self.infcx.probe_effect_var(vid) else {
|
||||
bug!("effect var should have been resolved");
|
||||
};
|
||||
CanonicalVarKind::Effect
|
||||
}
|
||||
ty::ConstKind::Infer(ty::InferConst::Fresh(_)) => {
|
||||
bug!("fresh var during canonicalization: {c:?}")
|
||||
ty::ConstKind::Infer(i) => {
|
||||
// FIXME: we should fold the ty too eventually
|
||||
match i {
|
||||
ty::InferConst::Var(vid) => {
|
||||
assert_eq!(
|
||||
self.infcx.root_ct_var(vid),
|
||||
vid,
|
||||
"region vid should have been resolved fully before canonicalization"
|
||||
);
|
||||
assert_eq!(
|
||||
self.infcx.probe_ct_var(vid),
|
||||
None,
|
||||
"region vid should have been resolved fully before canonicalization"
|
||||
);
|
||||
CanonicalVarKind::Const(self.infcx.universe_of_ct(vid).unwrap(), c.ty())
|
||||
}
|
||||
ty::InferConst::EffectVar(_) => CanonicalVarKind::Effect,
|
||||
ty::InferConst::Fresh(_) => todo!(),
|
||||
}
|
||||
}
|
||||
ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode {
|
||||
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
|
||||
ty::Placeholder {
|
||||
universe: placeholder.universe,
|
||||
bound: ty::BoundVar::from(self.variables.len()),
|
||||
},
|
||||
PlaceholderLike::new(placeholder.universe(), self.variables.len().into()),
|
||||
c.ty(),
|
||||
),
|
||||
CanonicalizeMode::Response { .. } => {
|
||||
@ -400,13 +396,10 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
|
||||
},
|
||||
ty::ConstKind::Param(_) => match self.canonicalize_mode {
|
||||
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
|
||||
ty::Placeholder {
|
||||
universe: ty::UniverseIndex::ROOT,
|
||||
bound: ty::BoundVar::from(self.variables.len()),
|
||||
},
|
||||
PlaceholderLike::new(ty::UniverseIndex::ROOT, self.variables.len().into()),
|
||||
c.ty(),
|
||||
),
|
||||
CanonicalizeMode::Response { .. } => bug!("param ty in response: {c:?}"),
|
||||
CanonicalizeMode::Response { .. } => panic!("param ty in response: {c:?}"),
|
||||
},
|
||||
ty::ConstKind::Bound(_, _)
|
||||
| ty::ConstKind::Unevaluated(_)
|
||||
@ -423,6 +416,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
|
||||
var
|
||||
}),
|
||||
);
|
||||
ty::Const::new_bound(self.infcx.tcx, self.binder_index, var, c.ty())
|
||||
|
||||
self.interner().mk_bound_const(self.binder_index, var, c.ty())
|
||||
}
|
||||
}
|
1
compiler/rustc_next_trait_solver/src/lib.rs
Normal file
1
compiler/rustc_next_trait_solver/src/lib.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod canonicalizer;
|
@ -218,20 +218,21 @@ where
|
||||
return ControlFlow::Continue(());
|
||||
}
|
||||
|
||||
let kind = match kind {
|
||||
ty::Inherent | ty::Projection => "associated type",
|
||||
ty::Weak => "type alias",
|
||||
ty::Opaque => unreachable!(),
|
||||
};
|
||||
self.def_id_visitor.visit_def_id(
|
||||
data.def_id,
|
||||
kind,
|
||||
match kind {
|
||||
ty::Inherent | ty::Projection => "associated type",
|
||||
ty::Weak => "type alias",
|
||||
ty::Opaque => unreachable!(),
|
||||
},
|
||||
&LazyDefPathStr { def_id: data.def_id, tcx },
|
||||
)?;
|
||||
|
||||
// This will also visit args if necessary, so we don't need to recurse.
|
||||
return if V::SHALLOW {
|
||||
ControlFlow::Continue(())
|
||||
} else if kind == ty::Projection {
|
||||
self.visit_projection_ty(data)
|
||||
} else {
|
||||
data.args.iter().try_for_each(|subst| subst.visit_with(self))
|
||||
};
|
||||
|
@ -5,6 +5,7 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
rustc_abi = { path = "../rustc_abi" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_middle = { path = "../rustc_middle" }
|
||||
|
@ -2,6 +2,7 @@ use rustc_middle::mir::{
|
||||
interpret::{alloc_range, AllocRange, Pointer},
|
||||
ConstValue,
|
||||
};
|
||||
use stable_mir::Error;
|
||||
|
||||
use crate::rustc_smir::{Stable, Tables};
|
||||
use stable_mir::mir::Mutability;
|
||||
@ -26,23 +27,35 @@ pub fn new_allocation<'tcx>(
|
||||
const_value: ConstValue<'tcx>,
|
||||
tables: &mut Tables<'tcx>,
|
||||
) -> Allocation {
|
||||
match const_value {
|
||||
try_new_allocation(ty, const_value, tables).unwrap()
|
||||
}
|
||||
|
||||
#[allow(rustc::usage_of_qualified_ty)]
|
||||
pub fn try_new_allocation<'tcx>(
|
||||
ty: rustc_middle::ty::Ty<'tcx>,
|
||||
const_value: ConstValue<'tcx>,
|
||||
tables: &mut Tables<'tcx>,
|
||||
) -> Result<Allocation, Error> {
|
||||
Ok(match const_value {
|
||||
ConstValue::Scalar(scalar) => {
|
||||
let size = scalar.size();
|
||||
let align = tables
|
||||
.tcx
|
||||
.layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty))
|
||||
.unwrap()
|
||||
.map_err(|e| e.stable(tables))?
|
||||
.align;
|
||||
let mut allocation = rustc_middle::mir::interpret::Allocation::uninit(size, align.abi);
|
||||
allocation
|
||||
.write_scalar(&tables.tcx, alloc_range(rustc_target::abi::Size::ZERO, size), scalar)
|
||||
.unwrap();
|
||||
.map_err(|e| e.stable(tables))?;
|
||||
allocation.stable(tables)
|
||||
}
|
||||
ConstValue::ZeroSized => {
|
||||
let align =
|
||||
tables.tcx.layout_of(rustc_middle::ty::ParamEnv::empty().and(ty)).unwrap().align;
|
||||
let align = tables
|
||||
.tcx
|
||||
.layout_of(rustc_middle::ty::ParamEnv::empty().and(ty))
|
||||
.map_err(|e| e.stable(tables))?
|
||||
.align;
|
||||
new_empty_allocation(align.abi)
|
||||
}
|
||||
ConstValue::Slice { data, meta } => {
|
||||
@ -51,8 +64,10 @@ pub fn new_allocation<'tcx>(
|
||||
let scalar_ptr = rustc_middle::mir::interpret::Scalar::from_pointer(ptr, &tables.tcx);
|
||||
let scalar_meta =
|
||||
rustc_middle::mir::interpret::Scalar::from_target_usize(meta, &tables.tcx);
|
||||
let layout =
|
||||
tables.tcx.layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty)).unwrap();
|
||||
let layout = tables
|
||||
.tcx
|
||||
.layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty))
|
||||
.map_err(|e| e.stable(tables))?;
|
||||
let mut allocation =
|
||||
rustc_middle::mir::interpret::Allocation::uninit(layout.size, layout.align.abi);
|
||||
allocation
|
||||
@ -61,14 +76,14 @@ pub fn new_allocation<'tcx>(
|
||||
alloc_range(rustc_target::abi::Size::ZERO, tables.tcx.data_layout.pointer_size),
|
||||
scalar_ptr,
|
||||
)
|
||||
.unwrap();
|
||||
.map_err(|e| e.stable(tables))?;
|
||||
allocation
|
||||
.write_scalar(
|
||||
&tables.tcx,
|
||||
alloc_range(tables.tcx.data_layout.pointer_size, scalar_meta.size()),
|
||||
scalar_meta,
|
||||
)
|
||||
.unwrap();
|
||||
.map_err(|e| e.stable(tables))?;
|
||||
allocation.stable(tables)
|
||||
}
|
||||
ConstValue::Indirect { alloc_id, offset } => {
|
||||
@ -76,11 +91,11 @@ pub fn new_allocation<'tcx>(
|
||||
let ty_size = tables
|
||||
.tcx
|
||||
.layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty))
|
||||
.unwrap()
|
||||
.map_err(|e| e.stable(tables))?
|
||||
.size;
|
||||
allocation_filter(&alloc.0, alloc_range(offset, ty_size), tables)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates an `Allocation` only from information within the `AllocRange`.
|
||||
|
@ -11,18 +11,29 @@ use stable_mir::compiler_interface::Context;
|
||||
use stable_mir::mir::alloc::GlobalAlloc;
|
||||
use stable_mir::mir::mono::{InstanceDef, StaticDef};
|
||||
use stable_mir::mir::Body;
|
||||
use stable_mir::target::{MachineInfo, MachineSize};
|
||||
use stable_mir::ty::{
|
||||
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, GenericArgs,
|
||||
LineInfo, PolyFnSig, RigidTy, Span, TyKind, VariantDef,
|
||||
LineInfo, PolyFnSig, RigidTy, Span, Ty, TyKind, VariantDef,
|
||||
};
|
||||
use stable_mir::{self, Crate, CrateItem, DefId, Error, Filename, ItemKind, Symbol};
|
||||
use std::cell::RefCell;
|
||||
|
||||
use crate::rustc_internal::{internal, RustcInternal};
|
||||
use crate::rustc_smir::builder::BodyBuilder;
|
||||
use crate::rustc_smir::{new_item_kind, smir_crate, Stable, Tables};
|
||||
use crate::rustc_smir::{alloc, new_item_kind, smir_crate, Stable, Tables};
|
||||
|
||||
impl<'tcx> Context for TablesWrapper<'tcx> {
|
||||
fn target_info(&self) -> MachineInfo {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
MachineInfo {
|
||||
endian: tables.tcx.data_layout.endian.stable(&mut *tables),
|
||||
pointer_width: MachineSize::from_bits(
|
||||
tables.tcx.data_layout.pointer_size.bits().try_into().unwrap(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn entry_fn(&self) -> Option<stable_mir::CrateItem> {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let tcx = tables.tcx;
|
||||
@ -382,6 +393,21 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
|
||||
Instance::resolve_closure(tables.tcx, def_id, args_ref, closure_kind).stable(&mut *tables)
|
||||
}
|
||||
|
||||
fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result<Allocation, Error> {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let instance = tables.instances[def];
|
||||
let result = tables.tcx.const_eval_instance(
|
||||
ParamEnv::reveal_all(),
|
||||
instance,
|
||||
Some(tables.tcx.def_span(instance.def_id())),
|
||||
);
|
||||
result
|
||||
.map(|const_val| {
|
||||
alloc::try_new_allocation(const_ty.internal(&mut *tables), const_val, &mut *tables)
|
||||
})
|
||||
.map_err(|e| e.stable(&mut *tables))?
|
||||
}
|
||||
|
||||
fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error> {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let def_id = def.0.internal(&mut *tables);
|
||||
|
22
compiler/rustc_smir/src/rustc_smir/convert/error.rs
Normal file
22
compiler/rustc_smir/src/rustc_smir/convert/error.rs
Normal file
@ -0,0 +1,22 @@
|
||||
//! Handle the conversion of different internal errors into a stable version.
|
||||
//!
|
||||
//! Currently we encode everything as [stable_mir::Error], which is represented as a string.
|
||||
use crate::rustc_smir::{Stable, Tables};
|
||||
use rustc_middle::mir::interpret::AllocError;
|
||||
use rustc_middle::ty::layout::LayoutError;
|
||||
|
||||
impl<'tcx> Stable<'tcx> for LayoutError<'tcx> {
|
||||
type T = stable_mir::Error;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
|
||||
stable_mir::Error::new(format!("{self:?}"))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for AllocError {
|
||||
type T = stable_mir::Error;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
|
||||
stable_mir::Error::new(format!("{self:?}"))
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ use stable_mir::ty::{IndexedVal, VariantIdx};
|
||||
|
||||
use crate::rustc_smir::{Stable, Tables};
|
||||
|
||||
mod error;
|
||||
mod mir;
|
||||
mod ty;
|
||||
|
||||
@ -76,3 +77,14 @@ impl<'tcx> Stable<'tcx> for rustc_span::Span {
|
||||
tables.create_span(*self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for rustc_abi::Endian {
|
||||
type T = stable_mir::target::Endian;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
|
||||
match self {
|
||||
rustc_abi::Endian::Little => stable_mir::target::Endian::Little,
|
||||
rustc_abi::Endian::Big => stable_mir::target::Endian::Big,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ rustc_index = { path = "../rustc_index" }
|
||||
rustc_infer = { path = "../rustc_infer" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_middle = { path = "../rustc_middle" }
|
||||
rustc_next_trait_solver = { path = "../rustc_next_trait_solver" }
|
||||
rustc_parse_format = { path = "../rustc_parse_format" }
|
||||
rustc_query_system = { path = "../rustc_query_system" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
|
@ -9,7 +9,6 @@
|
||||
//!
|
||||
//! [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::{
|
||||
inspect, response_no_constraints_raw, CanonicalResponse, QueryResult, Response,
|
||||
};
|
||||
@ -27,6 +26,7 @@ use rustc_middle::traits::solve::{
|
||||
};
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::{self, BoundVar, GenericArgKind, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_next_trait_solver::canonicalizer::{CanonicalizeMode, Canonicalizer};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use std::iter;
|
||||
use std::ops::Deref;
|
||||
|
@ -30,7 +30,6 @@ use rustc_middle::ty::{
|
||||
|
||||
mod alias_relate;
|
||||
mod assembly;
|
||||
mod canonicalize;
|
||||
mod eval_ctxt;
|
||||
mod fulfill;
|
||||
pub mod inspect;
|
||||
|
@ -157,18 +157,10 @@ where
|
||||
}
|
||||
|
||||
let mut region_constraints = QueryRegionConstraints::default();
|
||||
let (output, error_info, mut obligations) =
|
||||
Q::fully_perform_into(self, infcx, &mut region_constraints)
|
||||
.map_err(|_| {
|
||||
infcx.tcx.sess.span_delayed_bug(span, format!("error performing {self:?}"))
|
||||
})
|
||||
.and_then(|(output, error_info, obligations, certainty)| match certainty {
|
||||
Certainty::Proven => Ok((output, error_info, obligations)),
|
||||
Certainty::Ambiguous => Err(infcx
|
||||
.tcx
|
||||
.sess
|
||||
.span_delayed_bug(span, format!("ambiguity performing {self:?}"))),
|
||||
})?;
|
||||
let (output, error_info, mut obligations, _) =
|
||||
Q::fully_perform_into(self, infcx, &mut region_constraints).map_err(|_| {
|
||||
infcx.tcx.sess.span_delayed_bug(span, format!("error performing {self:?}"))
|
||||
})?;
|
||||
|
||||
// Typically, instantiating NLL query results does not
|
||||
// create obligations. However, in some cases there
|
||||
|
@ -4,7 +4,7 @@ use std::ops::ControlFlow;
|
||||
|
||||
use crate::fold::{FallibleTypeFolder, TypeFoldable};
|
||||
use crate::visit::{TypeVisitable, TypeVisitor};
|
||||
use crate::{Interner, Placeholder, UniverseIndex};
|
||||
use crate::{Interner, PlaceholderLike, UniverseIndex};
|
||||
|
||||
/// A "canonicalized" type `V` is one where all free inference
|
||||
/// variables have been rewritten to "canonical vars". These are
|
||||
@ -157,7 +157,7 @@ where
|
||||
}
|
||||
|
||||
impl<I: Interner> CanonicalVarInfo<I> {
|
||||
pub fn universe(&self) -> UniverseIndex {
|
||||
pub fn universe(self) -> UniverseIndex {
|
||||
self.kind.universe()
|
||||
}
|
||||
|
||||
@ -305,11 +305,11 @@ where
|
||||
}
|
||||
|
||||
impl<I: Interner> CanonicalVarKind<I> {
|
||||
pub fn universe(&self) -> UniverseIndex {
|
||||
pub fn universe(self) -> UniverseIndex {
|
||||
match self {
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) => *ui,
|
||||
CanonicalVarKind::Region(ui) => *ui,
|
||||
CanonicalVarKind::Const(ui, _) => *ui,
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) => ui,
|
||||
CanonicalVarKind::Region(ui) => ui,
|
||||
CanonicalVarKind::Const(ui, _) => ui,
|
||||
CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe(),
|
||||
CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe(),
|
||||
CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.universe(),
|
||||
|
@ -81,7 +81,7 @@ impl<I: Interner> DebugWithInfcx<I> for ConstKind<I> {
|
||||
match this.data {
|
||||
Param(param) => write!(f, "{param:?}"),
|
||||
Infer(var) => write!(f, "{:?}", &this.wrap(var)),
|
||||
Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var.clone()),
|
||||
Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var),
|
||||
Placeholder(placeholder) => write!(f, "{placeholder:?}"),
|
||||
Unevaluated(uv) => {
|
||||
write!(f, "{:?}", &this.wrap(uv))
|
||||
@ -146,15 +146,15 @@ impl<I: Interner> DebugWithInfcx<I> for InferConst {
|
||||
this: WithInfcx<'_, Infcx, &Self>,
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result {
|
||||
match this.infcx.universe_of_ct(*this.data) {
|
||||
None => write!(f, "{:?}", this.data),
|
||||
Some(universe) => match *this.data {
|
||||
InferConst::Var(vid) => write!(f, "?{}_{}c", vid.index(), universe.index()),
|
||||
InferConst::EffectVar(vid) => write!(f, "?{}_{}e", vid.index(), universe.index()),
|
||||
InferConst::Fresh(_) => {
|
||||
unreachable!()
|
||||
}
|
||||
match *this.data {
|
||||
InferConst::Var(vid) => match this.infcx.universe_of_ct(vid) {
|
||||
None => write!(f, "{:?}", this.data),
|
||||
Some(universe) => write!(f, "?{}_{}c", vid.index(), universe.index()),
|
||||
},
|
||||
InferConst::EffectVar(vid) => write!(f, "?{}e", vid.index()),
|
||||
InferConst::Fresh(_) => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,35 +1,50 @@
|
||||
use crate::{InferConst, InferTy, Interner, UniverseIndex};
|
||||
use crate::{ConstVid, InferCtxtLike, Interner, TyVid, UniverseIndex};
|
||||
|
||||
use core::fmt;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub trait InferCtxtLike {
|
||||
type Interner: Interner;
|
||||
|
||||
fn universe_of_ty(&self, ty: InferTy) -> Option<UniverseIndex>;
|
||||
|
||||
fn universe_of_lt(
|
||||
&self,
|
||||
lt: <Self::Interner as Interner>::InferRegion,
|
||||
) -> Option<UniverseIndex>;
|
||||
|
||||
fn universe_of_ct(&self, ct: InferConst) -> Option<UniverseIndex>;
|
||||
}
|
||||
|
||||
pub struct NoInfcx<I>(PhantomData<I>);
|
||||
|
||||
impl<I: Interner> InferCtxtLike for NoInfcx<I> {
|
||||
type Interner = I;
|
||||
|
||||
fn universe_of_ty(&self, _ty: InferTy) -> Option<UniverseIndex> {
|
||||
fn interner(&self) -> Self::Interner {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn universe_of_ty(&self, _ty: TyVid) -> Option<UniverseIndex> {
|
||||
None
|
||||
}
|
||||
|
||||
fn universe_of_ct(&self, _ct: InferConst) -> Option<UniverseIndex> {
|
||||
fn universe_of_lt(&self, _lt: I::InferRegion) -> Option<UniverseIndex> {
|
||||
None
|
||||
}
|
||||
|
||||
fn universe_of_lt(&self, _lt: <I as Interner>::InferRegion) -> Option<UniverseIndex> {
|
||||
fn universe_of_ct(&self, _ct: ConstVid) -> Option<UniverseIndex> {
|
||||
None
|
||||
}
|
||||
|
||||
fn root_ty_var(&self, vid: TyVid) -> TyVid {
|
||||
vid
|
||||
}
|
||||
|
||||
fn probe_ty_var(&self, _vid: TyVid) -> Option<I::Ty> {
|
||||
None
|
||||
}
|
||||
|
||||
fn root_lt_var(&self, vid: I::InferRegion) -> I::InferRegion {
|
||||
vid
|
||||
}
|
||||
|
||||
fn probe_lt_var(&self, _vid: I::InferRegion) -> Option<I::Region> {
|
||||
None
|
||||
}
|
||||
|
||||
fn root_ct_var(&self, vid: ConstVid) -> ConstVid {
|
||||
vid
|
||||
}
|
||||
|
||||
fn probe_ct_var(&self, _vid: ConstVid) -> Option<I::Const> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
40
compiler/rustc_type_ir/src/infcx.rs
Normal file
40
compiler/rustc_type_ir/src/infcx.rs
Normal file
@ -0,0 +1,40 @@
|
||||
use crate::{ConstVid, Interner, TyVid, UniverseIndex};
|
||||
|
||||
pub trait InferCtxtLike {
|
||||
type Interner: Interner;
|
||||
|
||||
fn interner(&self) -> Self::Interner;
|
||||
|
||||
fn universe_of_ty(&self, ty: TyVid) -> Option<UniverseIndex>;
|
||||
|
||||
/// Resolve `TyVid` to its root `TyVid`.
|
||||
fn root_ty_var(&self, vid: TyVid) -> TyVid;
|
||||
|
||||
/// Resolve `TyVid` to its inferred type, if it has been equated with a non-infer type.
|
||||
fn probe_ty_var(&self, vid: TyVid) -> Option<<Self::Interner as Interner>::Ty>;
|
||||
|
||||
fn universe_of_lt(
|
||||
&self,
|
||||
lt: <Self::Interner as Interner>::InferRegion,
|
||||
) -> Option<UniverseIndex>;
|
||||
|
||||
/// Resolve `InferRegion` to its root `InferRegion`.
|
||||
fn root_lt_var(
|
||||
&self,
|
||||
vid: <Self::Interner as Interner>::InferRegion,
|
||||
) -> <Self::Interner as Interner>::InferRegion;
|
||||
|
||||
/// Resolve `InferRegion` to its inferred region, if it has been equated with a non-infer region.
|
||||
fn probe_lt_var(
|
||||
&self,
|
||||
vid: <Self::Interner as Interner>::InferRegion,
|
||||
) -> Option<<Self::Interner as Interner>::Region>;
|
||||
|
||||
fn universe_of_ct(&self, ct: ConstVid) -> Option<UniverseIndex>;
|
||||
|
||||
/// Resolve `ConstVid` to its root `ConstVid`.
|
||||
fn root_ct_var(&self, vid: ConstVid) -> ConstVid;
|
||||
|
||||
/// Resolve `ConstVid` to its inferred type, if it has been equated with a non-infer type.
|
||||
fn probe_ct_var(&self, vid: ConstVid) -> Option<<Self::Interner as Interner>::Const>;
|
||||
}
|
@ -2,75 +2,113 @@ use smallvec::SmallVec;
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
|
||||
use crate::{BoundVar, DebugWithInfcx, Mutability, UniverseIndex};
|
||||
use crate::{
|
||||
BoundVar, CanonicalVarInfo, ConstKind, DebruijnIndex, DebugWithInfcx, Mutability, RegionKind,
|
||||
TyKind, UniverseIndex,
|
||||
};
|
||||
|
||||
pub trait Interner: Sized {
|
||||
type DefId: Clone + Debug + Hash + Ord;
|
||||
type AdtDef: Clone + Debug + Hash + Ord;
|
||||
type DefId: Copy + Debug + Hash + Ord;
|
||||
type AdtDef: Copy + Debug + Hash + Ord;
|
||||
|
||||
type GenericArgs: Clone
|
||||
type GenericArgs: Copy
|
||||
+ DebugWithInfcx<Self>
|
||||
+ Hash
|
||||
+ Ord
|
||||
+ IntoIterator<Item = Self::GenericArg>;
|
||||
type GenericArg: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type Term: Clone + Debug + Hash + Ord;
|
||||
type GenericArg: Copy + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type Term: Copy + Debug + Hash + Ord;
|
||||
|
||||
type Binder<T>;
|
||||
type TypeAndMut: Clone + Debug + Hash + Ord;
|
||||
type CanonicalVars: Clone + Debug + Hash + Eq;
|
||||
type TypeAndMut: Copy + Debug + Hash + Ord;
|
||||
type CanonicalVars: Copy + Debug + Hash + Eq + IntoIterator<Item = CanonicalVarInfo<Self>>;
|
||||
|
||||
// Kinds of tys
|
||||
type Ty: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type Tys: Clone + Debug + Hash + Ord + IntoIterator<Item = Self::Ty>;
|
||||
type AliasTy: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type ParamTy: Clone + Debug + Hash + Ord;
|
||||
type BoundTy: Clone + Debug + Hash + Ord;
|
||||
type PlaceholderTy: Clone + Debug + Hash + Ord + Placeholder;
|
||||
type Ty: Copy
|
||||
+ DebugWithInfcx<Self>
|
||||
+ Hash
|
||||
+ Ord
|
||||
+ Into<Self::GenericArg>
|
||||
+ IntoKind<Kind = TyKind<Self>>;
|
||||
type Tys: Copy + Debug + Hash + Ord + IntoIterator<Item = Self::Ty>;
|
||||
type AliasTy: Copy + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type ParamTy: Copy + Debug + Hash + Ord;
|
||||
type BoundTy: Copy + Debug + Hash + Ord;
|
||||
type PlaceholderTy: Copy + Debug + Hash + Ord + PlaceholderLike;
|
||||
|
||||
// Things stored inside of tys
|
||||
type ErrorGuaranteed: Clone + Debug + Hash + Ord;
|
||||
type BoundExistentialPredicates: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type PolyFnSig: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type AllocId: Clone + Debug + Hash + Ord;
|
||||
type ErrorGuaranteed: Copy + Debug + Hash + Ord;
|
||||
type BoundExistentialPredicates: Copy + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type PolyFnSig: Copy + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type AllocId: Copy + Debug + Hash + Ord;
|
||||
|
||||
// Kinds of consts
|
||||
type Const: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type AliasConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type PlaceholderConst: Clone + Debug + Hash + Ord + Placeholder;
|
||||
type ParamConst: Clone + Debug + Hash + Ord;
|
||||
type BoundConst: Clone + Debug + Hash + Ord;
|
||||
type ValueConst: Clone + Debug + Hash + Ord;
|
||||
type ExprConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type Const: Copy
|
||||
+ DebugWithInfcx<Self>
|
||||
+ Hash
|
||||
+ Ord
|
||||
+ Into<Self::GenericArg>
|
||||
+ IntoKind<Kind = ConstKind<Self>>
|
||||
+ ConstTy<Self>;
|
||||
type AliasConst: Copy + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type PlaceholderConst: Copy + Debug + Hash + Ord + PlaceholderLike;
|
||||
type ParamConst: Copy + Debug + Hash + Ord;
|
||||
type BoundConst: Copy + Debug + Hash + Ord;
|
||||
type ValueConst: Copy + Debug + Hash + Ord;
|
||||
type ExprConst: Copy + DebugWithInfcx<Self> + Hash + Ord;
|
||||
|
||||
// Kinds of regions
|
||||
type Region: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type EarlyParamRegion: Clone + Debug + Hash + Ord;
|
||||
type BoundRegion: Clone + Debug + Hash + Ord;
|
||||
type LateParamRegion: Clone + Debug + Hash + Ord;
|
||||
type InferRegion: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type PlaceholderRegion: Clone + Debug + Hash + Ord + Placeholder;
|
||||
type Region: Copy
|
||||
+ DebugWithInfcx<Self>
|
||||
+ Hash
|
||||
+ Ord
|
||||
+ Into<Self::GenericArg>
|
||||
+ IntoKind<Kind = RegionKind<Self>>;
|
||||
type EarlyParamRegion: Copy + Debug + Hash + Ord;
|
||||
type LateParamRegion: Copy + Debug + Hash + Ord;
|
||||
type BoundRegion: Copy + Debug + Hash + Ord;
|
||||
type InferRegion: Copy + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type PlaceholderRegion: Copy + Debug + Hash + Ord + PlaceholderLike;
|
||||
|
||||
// Predicates
|
||||
type Predicate: Clone + Debug + Hash + Eq;
|
||||
type TraitPredicate: Clone + Debug + Hash + Eq;
|
||||
type RegionOutlivesPredicate: Clone + Debug + Hash + Eq;
|
||||
type TypeOutlivesPredicate: Clone + Debug + Hash + Eq;
|
||||
type ProjectionPredicate: Clone + Debug + Hash + Eq;
|
||||
type NormalizesTo: Clone + Debug + Hash + Eq;
|
||||
type SubtypePredicate: Clone + Debug + Hash + Eq;
|
||||
type CoercePredicate: Clone + Debug + Hash + Eq;
|
||||
type ClosureKind: Clone + Debug + Hash + Eq;
|
||||
type Predicate: Copy + Debug + Hash + Eq;
|
||||
type TraitPredicate: Copy + Debug + Hash + Eq;
|
||||
type RegionOutlivesPredicate: Copy + Debug + Hash + Eq;
|
||||
type TypeOutlivesPredicate: Copy + Debug + Hash + Eq;
|
||||
type ProjectionPredicate: Copy + Debug + Hash + Eq;
|
||||
type NormalizesTo: Copy + Debug + Hash + Eq;
|
||||
type SubtypePredicate: Copy + Debug + Hash + Eq;
|
||||
type CoercePredicate: Copy + Debug + Hash + Eq;
|
||||
type ClosureKind: Copy + Debug + Hash + Eq;
|
||||
|
||||
fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Mutability);
|
||||
|
||||
fn mk_canonical_var_infos(self, infos: &[CanonicalVarInfo<Self>]) -> Self::CanonicalVars;
|
||||
|
||||
// FIXME: We should not have all these constructors on `Interner`, but as functions on some trait.
|
||||
fn mk_bound_ty(self, debruijn: DebruijnIndex, var: BoundVar) -> Self::Ty;
|
||||
fn mk_bound_region(self, debruijn: DebruijnIndex, var: BoundVar) -> Self::Region;
|
||||
fn mk_bound_const(self, debruijn: DebruijnIndex, var: BoundVar, ty: Self::Ty) -> Self::Const;
|
||||
}
|
||||
|
||||
/// Common capabilities of placeholder kinds
|
||||
pub trait Placeholder {
|
||||
fn universe(&self) -> UniverseIndex;
|
||||
fn var(&self) -> BoundVar;
|
||||
pub trait PlaceholderLike {
|
||||
fn universe(self) -> UniverseIndex;
|
||||
fn var(self) -> BoundVar;
|
||||
|
||||
fn with_updated_universe(self, ui: UniverseIndex) -> Self;
|
||||
|
||||
fn new(ui: UniverseIndex, var: BoundVar) -> Self;
|
||||
}
|
||||
|
||||
pub trait IntoKind {
|
||||
type Kind;
|
||||
|
||||
fn kind(self) -> Self::Kind;
|
||||
}
|
||||
|
||||
pub trait ConstTy<I: Interner> {
|
||||
fn ty(self) -> I::Ty;
|
||||
}
|
||||
|
||||
/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
|
||||
|
@ -4,6 +4,7 @@
|
||||
)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::usage_of_ty_tykind)]
|
||||
#![cfg_attr(feature = "nightly", allow(internal_features))]
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
@ -35,6 +36,7 @@ mod canonical;
|
||||
mod const_kind;
|
||||
mod debug;
|
||||
mod flags;
|
||||
mod infcx;
|
||||
mod interner;
|
||||
mod predicate_kind;
|
||||
mod region_kind;
|
||||
@ -43,13 +45,19 @@ pub use canonical::*;
|
||||
#[cfg(feature = "nightly")]
|
||||
pub use codec::*;
|
||||
pub use const_kind::*;
|
||||
pub use debug::{DebugWithInfcx, InferCtxtLike, WithInfcx};
|
||||
pub use debug::{DebugWithInfcx, WithInfcx};
|
||||
pub use flags::*;
|
||||
pub use infcx::InferCtxtLike;
|
||||
pub use interner::*;
|
||||
pub use predicate_kind::*;
|
||||
pub use region_kind::*;
|
||||
pub use ty_info::*;
|
||||
pub use ty_kind::*;
|
||||
pub use AliasKind::*;
|
||||
pub use DynKind::*;
|
||||
pub use InferTy::*;
|
||||
pub use RegionKind::*;
|
||||
pub use TyKind::*;
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
/// A [De Bruijn index][dbi] is a standard means of representing
|
||||
@ -337,6 +345,12 @@ impl UniverseIndex {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for UniverseIndex {
|
||||
fn default() -> Self {
|
||||
Self::ROOT
|
||||
}
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
|
||||
#[encodable]
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![allow(rustc::usage_of_ty_tykind)]
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
#[cfg(feature = "nightly")]
|
||||
@ -394,7 +392,7 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
|
||||
Float(float) => write!(f, "{float:?}"),
|
||||
Adt(d, s) => {
|
||||
write!(f, "{d:?}")?;
|
||||
let mut s = s.clone().into_iter();
|
||||
let mut s = s.into_iter();
|
||||
let first = s.next();
|
||||
match first {
|
||||
Some(first) => write!(f, "<{:?}", first)?,
|
||||
@ -412,7 +410,7 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
|
||||
Array(t, c) => write!(f, "[{:?}; {:?}]", &this.wrap(t), &this.wrap(c)),
|
||||
Slice(t) => write!(f, "[{:?}]", &this.wrap(t)),
|
||||
RawPtr(p) => {
|
||||
let (ty, mutbl) = I::ty_and_mut_to_parts(p.clone());
|
||||
let (ty, mutbl) = I::ty_and_mut_to_parts(*p);
|
||||
match mutbl {
|
||||
Mutability::Mut => write!(f, "*mut "),
|
||||
Mutability::Not => write!(f, "*const "),
|
||||
@ -442,7 +440,7 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
|
||||
Tuple(t) => {
|
||||
write!(f, "(")?;
|
||||
let mut count = 0;
|
||||
for ty in t.clone() {
|
||||
for ty in *t {
|
||||
if count > 0 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
@ -820,15 +818,15 @@ impl<I: Interner> DebugWithInfcx<I> for InferTy {
|
||||
this: WithInfcx<'_, Infcx, &Self>,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
use InferTy::*;
|
||||
match this.infcx.universe_of_ty(*this.data) {
|
||||
None => write!(f, "{:?}", this.data),
|
||||
Some(universe) => match *this.data {
|
||||
TyVar(ty_vid) => write!(f, "?{}_{}t", ty_vid.index(), universe.index()),
|
||||
IntVar(_) | FloatVar(_) | FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_) => {
|
||||
unreachable!()
|
||||
match this.data {
|
||||
InferTy::TyVar(vid) => {
|
||||
if let Some(universe) = this.infcx.universe_of_ty(*vid) {
|
||||
write!(f, "?{}_{}t", vid.index(), universe.index())
|
||||
} else {
|
||||
write!(f, "{:?}", this.data)
|
||||
}
|
||||
},
|
||||
}
|
||||
_ => write!(f, "{:?}", this.data),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ use std::cell::Cell;
|
||||
use crate::mir::alloc::{AllocId, GlobalAlloc};
|
||||
use crate::mir::mono::{Instance, InstanceDef, StaticDef};
|
||||
use crate::mir::Body;
|
||||
use crate::target::MachineInfo;
|
||||
use crate::ty::{
|
||||
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, GenericArgs,
|
||||
GenericPredicates, Generics, ImplDef, ImplTrait, LineInfo, PolyFnSig, RigidTy, Span, TraitDecl,
|
||||
@ -150,6 +151,9 @@ pub trait Context {
|
||||
/// Evaluate a static's initializer.
|
||||
fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error>;
|
||||
|
||||
/// Try to evaluate an instance into a constant.
|
||||
fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result<Allocation, Error>;
|
||||
|
||||
/// Retrieve global allocation for the given allocation ID.
|
||||
fn global_alloc(&self, id: AllocId) -> GlobalAlloc;
|
||||
|
||||
@ -157,6 +161,9 @@ pub trait Context {
|
||||
fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option<AllocId>;
|
||||
fn krate(&self, def_id: DefId) -> Crate;
|
||||
fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol;
|
||||
|
||||
/// Return information about the target machine.
|
||||
fn target_info(&self) -> MachineInfo;
|
||||
}
|
||||
|
||||
// A thread local variable that stores a pointer to the tables mapping between TyCtxt
|
||||
|
@ -6,11 +6,11 @@
|
||||
|
||||
use std::convert::From;
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
use std::{error, fmt};
|
||||
use std::{error, fmt, io};
|
||||
|
||||
macro_rules! error {
|
||||
($fmt: literal $(,)?) => { Error(format!($fmt)) };
|
||||
($fmt: literal, $($arg:tt)*) => { Error(format!($fmt, $($arg:tt)*)) };
|
||||
($fmt: literal, $($arg:tt)*) => { Error(format!($fmt, $($arg)*)) };
|
||||
}
|
||||
|
||||
/// An error type used to represent an error that has already been reported by the compiler.
|
||||
@ -79,3 +79,9 @@ where
|
||||
|
||||
impl error::Error for Error {}
|
||||
impl<T> error::Error for CompilerError<T> where T: Display + Debug {}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(value: io::Error) -> Self {
|
||||
Error(value.to_string())
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ pub mod compiler_interface;
|
||||
#[macro_use]
|
||||
pub mod error;
|
||||
pub mod mir;
|
||||
pub mod target;
|
||||
pub mod ty;
|
||||
pub mod visitor;
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
//! This module provides methods to retrieve allocation information, such as static variables.
|
||||
use crate::mir::mono::{Instance, StaticDef};
|
||||
use crate::target::{Endian, MachineInfo};
|
||||
use crate::ty::{Allocation, Binder, ExistentialTraitRef, IndexedVal, Ty};
|
||||
use crate::with;
|
||||
use crate::{with, Error};
|
||||
use std::io::Read;
|
||||
|
||||
/// An allocation in the SMIR global memory can be either a function pointer,
|
||||
/// a static, or a "real" allocation with some data in it.
|
||||
@ -38,7 +40,7 @@ impl GlobalAlloc {
|
||||
}
|
||||
|
||||
/// A unique identification number for each provenance
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct AllocId(usize);
|
||||
|
||||
impl IndexedVal for AllocId {
|
||||
@ -49,3 +51,33 @@ impl IndexedVal for AllocId {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Utility function used to read an allocation data into a unassigned integer.
|
||||
pub(crate) fn read_target_uint(mut bytes: &[u8]) -> Result<u128, Error> {
|
||||
let mut buf = [0u8; std::mem::size_of::<u128>()];
|
||||
match MachineInfo::target_endianess() {
|
||||
Endian::Little => {
|
||||
bytes.read(&mut buf)?;
|
||||
Ok(u128::from_le_bytes(buf))
|
||||
}
|
||||
Endian::Big => {
|
||||
bytes.read(&mut buf[16 - bytes.len()..])?;
|
||||
Ok(u128::from_be_bytes(buf))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Utility function used to read an allocation data into an assigned integer.
|
||||
pub(crate) fn read_target_int(mut bytes: &[u8]) -> Result<i128, Error> {
|
||||
let mut buf = [0u8; std::mem::size_of::<i128>()];
|
||||
match MachineInfo::target_endianess() {
|
||||
Endian::Little => {
|
||||
bytes.read(&mut buf)?;
|
||||
Ok(i128::from_le_bytes(buf))
|
||||
}
|
||||
Endian::Big => {
|
||||
bytes.read(&mut buf[16 - bytes.len()..])?;
|
||||
Ok(i128::from_be_bytes(buf))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ pub struct Body {
|
||||
pub(super) arg_count: usize,
|
||||
|
||||
/// Debug information pertaining to user variables, including captures.
|
||||
pub(super) var_debug_info: Vec<VarDebugInfo>,
|
||||
pub var_debug_info: Vec<VarDebugInfo>,
|
||||
}
|
||||
|
||||
pub type BasicBlockIdx = usize;
|
||||
@ -616,6 +616,24 @@ pub struct VarDebugInfo {
|
||||
pub argument_index: Option<u16>,
|
||||
}
|
||||
|
||||
impl VarDebugInfo {
|
||||
/// Return a local variable if this info is related to one.
|
||||
pub fn local(&self) -> Option<Local> {
|
||||
match &self.value {
|
||||
VarDebugInfoContents::Place(place) if place.projection.is_empty() => Some(place.local),
|
||||
VarDebugInfoContents::Place(_) | VarDebugInfoContents::Const(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a constant if this info is related to one.
|
||||
pub fn constant(&self) -> Option<&ConstOperand> {
|
||||
match &self.value {
|
||||
VarDebugInfoContents::Place(_) => None,
|
||||
VarDebugInfoContents::Const(const_op) => Some(const_op),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type SourceScope = u32;
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
@ -832,7 +850,7 @@ pub enum MutBorrowKind {
|
||||
ClosureCapture,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum Mutability {
|
||||
Not,
|
||||
Mut,
|
||||
|
@ -132,6 +132,14 @@ impl Instance {
|
||||
pub fn is_empty_shim(&self) -> bool {
|
||||
self.kind == InstanceKind::Shim && with(|cx| cx.is_empty_drop_shim(self.def))
|
||||
}
|
||||
|
||||
/// Try to constant evaluate the instance into a constant with the given type.
|
||||
///
|
||||
/// This can be used to retrieve a constant that represents an intrinsic return such as
|
||||
/// `type_id`.
|
||||
pub fn try_const_eval(&self, const_ty: Ty) -> Result<Allocation, Error> {
|
||||
with(|cx| cx.eval_instance(self.def, const_ty))
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Instance {
|
||||
@ -212,7 +220,7 @@ impl TryFrom<CrateItem> for StaticDef {
|
||||
type Error = crate::Error;
|
||||
|
||||
fn try_from(value: CrateItem) -> Result<Self, Self::Error> {
|
||||
if matches!(value.kind(), ItemKind::Static | ItemKind::Const) {
|
||||
if matches!(value.kind(), ItemKind::Static) {
|
||||
Ok(StaticDef(value.0))
|
||||
} else {
|
||||
Err(Error::new(format!("Expected a static item, but found: {value:?}")))
|
||||
|
50
compiler/stable_mir/src/target.rs
Normal file
50
compiler/stable_mir/src/target.rs
Normal file
@ -0,0 +1,50 @@
|
||||
//! Provide information about the machine that this is being compiled into.
|
||||
|
||||
use crate::compiler_interface::with;
|
||||
|
||||
/// The properties of the target machine being compiled into.
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct MachineInfo {
|
||||
pub endian: Endian,
|
||||
pub pointer_width: MachineSize,
|
||||
}
|
||||
|
||||
impl MachineInfo {
|
||||
pub fn target() -> MachineInfo {
|
||||
with(|cx| cx.target_info().clone())
|
||||
}
|
||||
|
||||
pub fn target_endianess() -> Endian {
|
||||
with(|cx| cx.target_info().endian)
|
||||
}
|
||||
|
||||
pub fn target_pointer_width() -> MachineSize {
|
||||
with(|cx| cx.target_info().pointer_width)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Endian {
|
||||
Little,
|
||||
Big,
|
||||
}
|
||||
|
||||
/// Represent the size of a component.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct MachineSize {
|
||||
num_bits: usize,
|
||||
}
|
||||
|
||||
impl MachineSize {
|
||||
pub fn bytes(self) -> usize {
|
||||
self.num_bits / 8
|
||||
}
|
||||
|
||||
pub fn bits(self) -> usize {
|
||||
self.num_bits
|
||||
}
|
||||
|
||||
pub fn from_bits(num_bits: usize) -> MachineSize {
|
||||
MachineSize { num_bits }
|
||||
}
|
||||
}
|
@ -4,9 +4,11 @@ use super::{
|
||||
with, DefId, Error, Symbol,
|
||||
};
|
||||
use crate::crate_def::CrateDef;
|
||||
use crate::mir::alloc::AllocId;
|
||||
use crate::mir::alloc::{read_target_int, read_target_uint, AllocId};
|
||||
use crate::target::MachineInfo;
|
||||
use crate::{Filename, Opaque};
|
||||
use std::fmt::{self, Debug, Display, Formatter};
|
||||
use std::ops::Range;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Ty(pub usize);
|
||||
@ -366,6 +368,19 @@ pub enum IntTy {
|
||||
I128,
|
||||
}
|
||||
|
||||
impl IntTy {
|
||||
pub fn num_bytes(self) -> usize {
|
||||
match self {
|
||||
IntTy::Isize => crate::target::MachineInfo::target_pointer_width().bytes().into(),
|
||||
IntTy::I8 => 1,
|
||||
IntTy::I16 => 2,
|
||||
IntTy::I32 => 4,
|
||||
IntTy::I64 => 8,
|
||||
IntTy::I128 => 16,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum UintTy {
|
||||
Usize,
|
||||
@ -376,6 +391,19 @@ pub enum UintTy {
|
||||
U128,
|
||||
}
|
||||
|
||||
impl UintTy {
|
||||
pub fn num_bytes(self) -> usize {
|
||||
match self {
|
||||
UintTy::Usize => crate::target::MachineInfo::target_pointer_width().bytes().into(),
|
||||
UintTy::U8 => 1,
|
||||
UintTy::U16 => 2,
|
||||
UintTy::U32 => 4,
|
||||
UintTy::U64 => 8,
|
||||
UintTy::U128 => 16,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum FloatTy {
|
||||
F32,
|
||||
@ -821,21 +849,21 @@ pub struct BoundTy {
|
||||
pub type Bytes = Vec<Option<u8>>;
|
||||
pub type Size = usize;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct Prov(pub AllocId);
|
||||
pub type Align = u64;
|
||||
pub type Promoted = u32;
|
||||
pub type InitMaskMaterialized = Vec<u64>;
|
||||
|
||||
/// Stores the provenance information of pointers stored in memory.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub struct ProvenanceMap {
|
||||
/// Provenance in this map applies from the given offset for an entire pointer-size worth of
|
||||
/// bytes. Two entries in this map are always at least a pointer size apart.
|
||||
pub ptrs: Vec<(Size, Prov)>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub struct Allocation {
|
||||
pub bytes: Bytes,
|
||||
pub provenance: ProvenanceMap,
|
||||
@ -843,6 +871,74 @@ pub struct Allocation {
|
||||
pub mutability: Mutability,
|
||||
}
|
||||
|
||||
impl Allocation {
|
||||
/// Get a vector of bytes for an Allocation that has been fully initialized
|
||||
pub fn raw_bytes(&self) -> Result<Vec<u8>, Error> {
|
||||
self.bytes
|
||||
.iter()
|
||||
.copied()
|
||||
.collect::<Option<Vec<_>>>()
|
||||
.ok_or_else(|| error!("Found uninitialized bytes: `{:?}`", self.bytes))
|
||||
}
|
||||
|
||||
/// Read a uint value from the specified range.
|
||||
pub fn read_partial_uint(&self, range: Range<usize>) -> Result<u128, Error> {
|
||||
if range.end - range.start > 16 {
|
||||
return Err(error!("Allocation is bigger than largest integer"));
|
||||
}
|
||||
if range.end > self.bytes.len() {
|
||||
return Err(error!(
|
||||
"Range is out of bounds. Allocation length is `{}`, but requested range `{:?}`",
|
||||
self.bytes.len(),
|
||||
range
|
||||
));
|
||||
}
|
||||
let raw = self.bytes[range]
|
||||
.iter()
|
||||
.copied()
|
||||
.collect::<Option<Vec<_>>>()
|
||||
.ok_or_else(|| error!("Found uninitialized bytes: `{:?}`", self.bytes))?;
|
||||
read_target_uint(&raw)
|
||||
}
|
||||
|
||||
/// Read this allocation and try to convert it to an unassigned integer.
|
||||
pub fn read_uint(&self) -> Result<u128, Error> {
|
||||
if self.bytes.len() > 16 {
|
||||
return Err(error!("Allocation is bigger than largest integer"));
|
||||
}
|
||||
let raw = self.raw_bytes()?;
|
||||
read_target_uint(&raw)
|
||||
}
|
||||
|
||||
/// Read this allocation and try to convert it to a signed integer.
|
||||
pub fn read_int(&self) -> Result<i128, Error> {
|
||||
if self.bytes.len() > 16 {
|
||||
return Err(error!("Allocation is bigger than largest integer"));
|
||||
}
|
||||
let raw = self.raw_bytes()?;
|
||||
read_target_int(&raw)
|
||||
}
|
||||
|
||||
/// Read this allocation and try to convert it to a boolean.
|
||||
pub fn read_bool(&self) -> Result<bool, Error> {
|
||||
match self.read_int()? {
|
||||
0 => Ok(false),
|
||||
1 => Ok(true),
|
||||
val @ _ => Err(error!("Unexpected value for bool: `{val}`")),
|
||||
}
|
||||
}
|
||||
|
||||
/// Read this allocation as a pointer and return whether it represents a `null` pointer.
|
||||
pub fn is_null(&self) -> Result<bool, Error> {
|
||||
let len = self.bytes.len();
|
||||
let ptr_len = MachineInfo::target_pointer_width().bytes();
|
||||
if len != ptr_len {
|
||||
return Err(error!("Expected width of pointer (`{ptr_len}`), but found: `{len}`"));
|
||||
}
|
||||
Ok(self.read_uint()? == 0 && self.provenance.ptrs.is_empty())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum ConstantKind {
|
||||
Allocated(Allocation),
|
||||
|
@ -23,12 +23,16 @@ extern crate stable_mir;
|
||||
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_smir::rustc_internal;
|
||||
use stable_mir::{CrateItem, CrateItems, ItemKind};
|
||||
use stable_mir::crate_def::CrateDef;
|
||||
use stable_mir::mir::alloc::GlobalAlloc;
|
||||
use stable_mir::mir::mono::StaticDef;
|
||||
use stable_mir::mir::mono::{Instance, InstanceKind, StaticDef};
|
||||
use stable_mir::mir::{Body, TerminatorKind};
|
||||
use stable_mir::ty::{Allocation, ConstantKind, RigidTy, TyKind};
|
||||
use stable_mir::{CrateItem, CrateItems, ItemKind};
|
||||
use std::ascii::Char;
|
||||
use std::assert_matches::assert_matches;
|
||||
use std::cmp::{max, min};
|
||||
use std::collections::HashMap;
|
||||
use std::io::Write;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
@ -40,6 +44,9 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
|
||||
let items = stable_mir::all_local_items();
|
||||
check_foo(*get_item(&items, (ItemKind::Static, "FOO")).unwrap());
|
||||
check_bar(*get_item(&items, (ItemKind::Static, "BAR")).unwrap());
|
||||
check_len(*get_item(&items, (ItemKind::Static, "LEN")).unwrap());
|
||||
check_other_consts(*get_item(&items, (ItemKind::Fn, "other_consts")).unwrap());
|
||||
check_type_id(*get_item(&items, (ItemKind::Fn, "check_type_id")).unwrap());
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
|
||||
@ -76,6 +83,110 @@ fn check_bar(item: CrateItem) {
|
||||
assert_eq!(allocation.bytes[0].unwrap(), Char::CapitalB.to_u8());
|
||||
assert_eq!(allocation.bytes[1].unwrap(), Char::SmallA.to_u8());
|
||||
assert_eq!(allocation.bytes[2].unwrap(), Char::SmallR.to_u8());
|
||||
assert_eq!(std::str::from_utf8(&allocation.raw_bytes().unwrap()), Ok("Bar"));
|
||||
}
|
||||
|
||||
/// Check the allocation data for constants used in `other_consts` function.
|
||||
fn check_other_consts(item: CrateItem) {
|
||||
// Instance body will force constant evaluation.
|
||||
let body = Instance::try_from(item).unwrap().body().unwrap();
|
||||
let assigns = collect_consts(&body);
|
||||
assert_eq!(assigns.len(), 9);
|
||||
for (name, alloc) in assigns {
|
||||
match name.as_str() {
|
||||
"_max_u128" => {
|
||||
assert_eq!(alloc.read_uint(), Ok(u128::MAX), "Failed parsing allocation: {alloc:?}")
|
||||
}
|
||||
"_min_i128" => {
|
||||
assert_eq!(alloc.read_int(), Ok(i128::MIN), "Failed parsing allocation: {alloc:?}")
|
||||
}
|
||||
"_max_i8" => {
|
||||
assert_eq!(
|
||||
alloc.read_int().unwrap() as i8,
|
||||
i8::MAX,
|
||||
"Failed parsing allocation: {alloc:?}"
|
||||
)
|
||||
}
|
||||
"_char" => {
|
||||
assert_eq!(
|
||||
char::from_u32(alloc.read_uint().unwrap() as u32),
|
||||
Some('x'),
|
||||
"Failed parsing allocation: {alloc:?}"
|
||||
)
|
||||
}
|
||||
"_false" => {
|
||||
assert_eq!(alloc.read_bool(), Ok(false), "Failed parsing allocation: {alloc:?}")
|
||||
}
|
||||
"_true" => {
|
||||
assert_eq!(alloc.read_bool(), Ok(true), "Failed parsing allocation: {alloc:?}")
|
||||
}
|
||||
"_ptr" => {
|
||||
assert_eq!(alloc.is_null(), Ok(false), "Failed parsing allocation: {alloc:?}")
|
||||
}
|
||||
"_null_ptr" => {
|
||||
assert_eq!(alloc.is_null(), Ok(true), "Failed parsing allocation: {alloc:?}")
|
||||
}
|
||||
"_tuple" => {
|
||||
// The order of fields is not guaranteed.
|
||||
let first = alloc.read_partial_uint(0..4).unwrap();
|
||||
let second = alloc.read_partial_uint(4..8).unwrap();
|
||||
assert_eq!(max(first, second) as u32, u32::MAX);
|
||||
assert_eq!(min(first, second), 10);
|
||||
}
|
||||
_ => {
|
||||
unreachable!("{name} -- {alloc:?}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Check that we can retrieve the type id of char and bool, and that they have different values.
|
||||
fn check_type_id(item: CrateItem) {
|
||||
let body = Instance::try_from(item).unwrap().body().unwrap();
|
||||
let mut ids: Vec<u128> = vec![];
|
||||
for term in body.blocks.iter().map(|bb| &bb.terminator) {
|
||||
match &term.kind {
|
||||
TerminatorKind::Call { func, destination, .. } => {
|
||||
let TyKind::RigidTy(ty) = func.ty(body.locals()).unwrap().kind() else {
|
||||
unreachable!()
|
||||
};
|
||||
let RigidTy::FnDef(def, args) = ty else { unreachable!() };
|
||||
let instance = Instance::resolve(def, &args).unwrap();
|
||||
assert_eq!(instance.kind, InstanceKind::Intrinsic);
|
||||
let dest_ty = destination.ty(body.locals()).unwrap();
|
||||
let alloc = instance.try_const_eval(dest_ty).unwrap();
|
||||
ids.push(alloc.read_uint().unwrap());
|
||||
}
|
||||
_ => { /* Do nothing */ }
|
||||
}
|
||||
}
|
||||
assert_eq!(ids.len(), 2);
|
||||
assert_ne!(ids[0], ids[1]);
|
||||
}
|
||||
|
||||
/// Collects all the constant assignments.
|
||||
pub fn collect_consts(body: &Body) -> HashMap<String, &Allocation> {
|
||||
body.var_debug_info
|
||||
.iter()
|
||||
.filter_map(|info| {
|
||||
info.constant().map(|const_op| {
|
||||
let ConstantKind::Allocated(alloc) = const_op.const_.kind() else { unreachable!() };
|
||||
(info.name.clone(), alloc)
|
||||
})
|
||||
})
|
||||
.collect::<HashMap<_, _>>()
|
||||
}
|
||||
|
||||
/// Check the allocation data for `LEN`.
|
||||
///
|
||||
/// ```no_run
|
||||
/// static LEN: usize = 2;
|
||||
/// ```
|
||||
fn check_len(item: CrateItem) {
|
||||
let def = StaticDef::try_from(item).unwrap();
|
||||
let alloc = def.eval_initializer().unwrap();
|
||||
assert!(alloc.provenance.ptrs.is_empty());
|
||||
assert_eq!(alloc.read_uint(), Ok(2));
|
||||
}
|
||||
|
||||
// Use internal API to find a function in a crate.
|
||||
@ -83,9 +194,7 @@ fn get_item<'a>(
|
||||
items: &'a CrateItems,
|
||||
item: (ItemKind, &str),
|
||||
) -> Option<&'a stable_mir::CrateItem> {
|
||||
items.iter().find(|crate_item| {
|
||||
(item.0 == crate_item.kind()) && crate_item.name() == item.1
|
||||
})
|
||||
items.iter().find(|crate_item| (item.0 == crate_item.kind()) && crate_item.name() == item.1)
|
||||
}
|
||||
|
||||
/// This test will generate and analyze a dummy crate using the stable mir.
|
||||
@ -109,11 +218,36 @@ fn generate_input(path: &str) -> std::io::Result<()> {
|
||||
write!(
|
||||
file,
|
||||
r#"
|
||||
#![feature(core_intrinsics)]
|
||||
use std::intrinsics::type_id;
|
||||
|
||||
static LEN: usize = 2;
|
||||
static FOO: [&str; 2] = ["hi", "there"];
|
||||
static BAR: &str = "Bar";
|
||||
const NULL: *const u8 = std::ptr::null();
|
||||
const TUPLE: (u32, u32) = (10, u32::MAX);
|
||||
|
||||
fn other_consts() {{
|
||||
let _max_u128 = u128::MAX;
|
||||
let _min_i128 = i128::MIN;
|
||||
let _max_i8 = i8::MAX;
|
||||
let _char = 'x';
|
||||
let _false = false;
|
||||
let _true = true;
|
||||
let _ptr = &BAR;
|
||||
let _null_ptr: *const u8 = NULL;
|
||||
let _tuple = TUPLE;
|
||||
}}
|
||||
|
||||
fn check_type_id() {{
|
||||
let _char_id = type_id::<char>();
|
||||
let _bool_id = type_id::<bool>();
|
||||
}}
|
||||
|
||||
pub fn main() {{
|
||||
println!("{{FOO:?}}! {{BAR}}");
|
||||
assert_eq!(FOO.len(), LEN);
|
||||
other_consts();
|
||||
}}"#
|
||||
)?;
|
||||
Ok(())
|
||||
|
@ -4,8 +4,8 @@ error[E0308]: const not compatible with trait
|
||||
LL | const NAME: &'a str = "unit";
|
||||
| ^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
||||
|
|
||||
= note: expected reference `&'static str`
|
||||
found reference `&'a str`
|
||||
= note: expected reference `&'static _`
|
||||
found reference `&'a _`
|
||||
note: the lifetime `'a` as defined here...
|
||||
--> $DIR/associated-const-impl-wrong-lifetime.rs:6:6
|
||||
|
|
||||
|
@ -4,8 +4,8 @@ error[E0308]: mismatched types
|
||||
LL | debug_assert_eq!(iter.next(), Some(value));
|
||||
| ^^^^^^^^^^^ expected `Option<<I as Iterator>::Item>`, found `Option<&<I as Iterator>::Item>`
|
||||
|
|
||||
= note: expected enum `Option<<I as Iterator>::Item>`
|
||||
found enum `Option<&<I as Iterator>::Item>`
|
||||
= note: expected enum `Option<_>`
|
||||
found enum `Option<&_>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -9,8 +9,8 @@ note: type in trait
|
||||
|
|
||||
LL | fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: expected signature `fn(&i32) -> Pin<Box<dyn Future<Output = i32>>>`
|
||||
found signature `fn(&i32) -> impl Future<Output = i32>`
|
||||
= note: expected signature `fn(&_) -> Pin<Box<dyn Future<Output = i32>>>`
|
||||
found signature `fn(&_) -> impl Future<Output = i32>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -22,8 +22,8 @@ error[E0308]: method not compatible with trait
|
||||
LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
||||
|
|
||||
= note: expected signature `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)`
|
||||
found signature `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)`
|
||||
= note: expected signature `fn(&'a _, Inv<'c>, Inv<'c>, Inv<'_>)`
|
||||
found signature `fn(&'a _, Inv<'_>, Inv<'c>, Inv<'_>)`
|
||||
note: the lifetime `'c` as defined here...
|
||||
--> $DIR/regions-bound-missing-bound-in-impl.rs:27:24
|
||||
|
|
||||
@ -41,8 +41,8 @@ error[E0308]: method not compatible with trait
|
||||
LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
||||
|
|
||||
= note: expected signature `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)`
|
||||
found signature `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)`
|
||||
= note: expected signature `fn(&'a _, Inv<'c>, Inv<'c>, Inv<'_>)`
|
||||
found signature `fn(&'a _, Inv<'_>, Inv<'c>, Inv<'_>)`
|
||||
note: the lifetime `'c` as defined here...
|
||||
--> $DIR/regions-bound-missing-bound-in-impl.rs:27:24
|
||||
|
|
||||
|
@ -4,8 +4,8 @@ error[E0308]: mismatched types
|
||||
LL | val
|
||||
| ^^^ expected `Box<dyn MyTrait>`, found `&Box<dyn MyTrait>`
|
||||
|
|
||||
= note: expected struct `Box<(dyn MyTrait + 'static)>`
|
||||
found reference `&Box<(dyn MyTrait + 'static)>`
|
||||
= note: expected struct `Box<_>`
|
||||
found reference `&Box<_>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -25,8 +25,8 @@ error[E0308]: mismatched types
|
||||
LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
|
||||
| ^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `fn(&u32)`
|
||||
found fn pointer `for<'a> fn(&'a u32)`
|
||||
= note: expected fn pointer `fn(&_)`
|
||||
found fn pointer `for<'a> fn(&'a _)`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/expect-fn-supply-fn.rs:39:50
|
||||
@ -34,8 +34,8 @@ error[E0308]: mismatched types
|
||||
LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
|
||||
| ^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'a> fn(&'a u32)`
|
||||
found fn pointer `fn(&u32)`
|
||||
= note: expected fn pointer `for<'a> fn(&'a _)`
|
||||
found fn pointer `fn(&_)`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/expect-fn-supply-fn.rs:48:50
|
||||
@ -43,8 +43,8 @@ error[E0308]: mismatched types
|
||||
LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
|
||||
| ^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'a> fn(&'a u32)`
|
||||
found fn pointer `fn(&u32)`
|
||||
= note: expected fn pointer `for<'a> fn(&'a _)`
|
||||
found fn pointer `fn(&_)`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
@ -6,8 +6,8 @@ LL | foo(move |x| v);
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected closure signature `fn(char) -> _`
|
||||
found closure signature `for<'a> fn(&'a char) -> _`
|
||||
= note: expected closure signature `fn(_) -> _`
|
||||
found closure signature `for<'a> fn(&'a _) -> _`
|
||||
note: closure inferred to have a different signature due to this bound
|
||||
--> $DIR/multiple-fn-bounds.rs:1:11
|
||||
|
|
||||
|
@ -35,20 +35,20 @@ fn main() {
|
||||
// suggest removing reference
|
||||
let c: fn(u32) -> u32 = &foo;
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected fn pointer `fn(u32) -> u32`
|
||||
//~| found reference `&fn(u32) -> u32 {foo}`
|
||||
//~| expected fn pointer `fn(_) -> _`
|
||||
//~| found reference `&fn(_) -> _ {foo}`
|
||||
|
||||
// suggest using reference
|
||||
let d: &fn(u32) -> u32 = foo;
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected reference `&fn(u32) -> u32`
|
||||
//~| found fn item `fn(u32) -> u32 {foo}`
|
||||
//~| expected reference `&fn(_) -> _`
|
||||
//~| found fn item `fn(_) -> _ {foo}`
|
||||
|
||||
// suggest casting with reference
|
||||
let e: &fn(u32) -> u32 = &foo;
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected reference `&fn(u32) -> u32`
|
||||
//~| found reference `&fn(u32) -> u32 {foo}`
|
||||
//~| expected reference `&fn(_) -> _`
|
||||
//~| found reference `&fn(_) -> _ {foo}`
|
||||
|
||||
// OK
|
||||
let mut z: fn(u32) -> u32 = foo as fn(u32) -> u32;
|
||||
|
@ -6,8 +6,8 @@ LL | let g = if n % 2 == 0 { &foo } else { &bar };
|
||||
| |
|
||||
| expected because of this
|
||||
|
|
||||
= note: expected reference `&fn(u32) -> u32 {foo}`
|
||||
found reference `&fn(u32) -> u32 {bar}`
|
||||
= note: expected reference `&fn(_) -> _ {foo}`
|
||||
found reference `&fn(_) -> _ {bar}`
|
||||
= note: different fn items have unique types, even if their signatures are the same
|
||||
= help: consider casting both fn items to fn pointers using `as fn(u32) -> u32`
|
||||
|
||||
@ -47,8 +47,8 @@ LL | let c: fn(u32) -> u32 = &foo;
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected fn pointer `fn(u32) -> u32`
|
||||
found reference `&fn(u32) -> u32 {foo}`
|
||||
= note: expected fn pointer `fn(_) -> _`
|
||||
found reference `&fn(_) -> _ {foo}`
|
||||
help: consider removing the reference
|
||||
|
|
||||
LL | let c: fn(u32) -> u32 = foo;
|
||||
@ -62,8 +62,8 @@ LL | let d: &fn(u32) -> u32 = foo;
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&fn(u32) -> u32`
|
||||
found fn item `fn(u32) -> u32 {foo}`
|
||||
= note: expected reference `&fn(_) -> _`
|
||||
found fn item `fn(_) -> _ {foo}`
|
||||
help: consider using a reference
|
||||
|
|
||||
LL | let d: &fn(u32) -> u32 = &foo;
|
||||
@ -77,8 +77,8 @@ LL | let e: &fn(u32) -> u32 = &foo;
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&fn(u32) -> u32`
|
||||
found reference `&fn(u32) -> u32 {foo}`
|
||||
= note: expected reference `&fn(_) -> _`
|
||||
found reference `&fn(_) -> _ {foo}`
|
||||
= note: fn items are distinct from fn pointers
|
||||
help: consider casting to a fn pointer
|
||||
|
|
||||
|
@ -9,8 +9,8 @@ LL | fn copy(&self) -> Self::Gat<'_> where T: Copy {
|
||||
LL | *self.test()
|
||||
| ^^^^^^^^^^^^ expected `&T`, found type parameter `T`
|
||||
|
|
||||
= note: expected reference `&T`
|
||||
found type parameter `T`
|
||||
= note: expected reference `&_`
|
||||
found type parameter `_`
|
||||
help: consider removing deref here
|
||||
|
|
||||
LL - *self.test()
|
||||
|
@ -8,8 +8,8 @@ LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u3
|
||||
LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) }
|
||||
| |_____________________________________________- in this macro invocation
|
||||
|
|
||||
= note: expected enum `Option<for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32>`
|
||||
found enum `Option<for<'a> fn(&'a u32, &'a u32) -> &'a u32>`
|
||||
= note: expected enum `Option<for<'a, 'b> fn(&'a _, &'b _) -> &'a _>`
|
||||
found enum `Option<for<'a> fn(&'a _, &'a _) -> &'a _>`
|
||||
= note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -8,8 +8,8 @@ LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32),
|
||||
LL | | fn(&'x u32)) }
|
||||
| |______________- in this macro invocation
|
||||
|
|
||||
= note: expected enum `Option<for<'a> fn(&'a u32)>`
|
||||
found enum `Option<fn(&u32)>`
|
||||
= note: expected enum `Option<for<'a> fn(&'a _)>`
|
||||
found enum `Option<fn(&_)>`
|
||||
= note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -6,8 +6,8 @@ LL | let _: for<'b> fn(&'b u32) = foo();
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected fn pointer `for<'b> fn(&'b u32)`
|
||||
found fn pointer `fn(&u32)`
|
||||
= note: expected fn pointer `for<'b> fn(&'b _)`
|
||||
found fn pointer `fn(&_)`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -15,8 +15,8 @@ note: type in trait
|
||||
|
|
||||
LL | fn bar(&self) -> impl Sized;
|
||||
| ^^^^^^^^^^
|
||||
= note: expected signature `fn(&U) -> impl Sized`
|
||||
found signature `fn(&U) -> U`
|
||||
= note: expected signature `fn(&_) -> impl Sized`
|
||||
found signature `fn(&_) -> U`
|
||||
|
||||
error: method with return-position `impl Trait` in trait cannot be specialized
|
||||
--> $DIR/specialization-broken.rs:15:5
|
||||
|
@ -18,8 +18,8 @@ LL | fn eq(&self, _other: &(Foo, i32)) -> bool {
|
||||
| expected `a::Bar`, found opaque type
|
||||
| help: change the parameter type to match the trait: `&(a::Bar, i32)`
|
||||
|
|
||||
= note: expected signature `fn(&a::Bar, &(a::Bar, i32)) -> _`
|
||||
found signature `fn(&a::Bar, &(a::Foo, i32)) -> _`
|
||||
= note: expected signature `fn(&a::Bar, &(a::Bar, _)) -> _`
|
||||
found signature `fn(&a::Bar, &(a::Foo, _)) -> _`
|
||||
|
||||
error: unconstrained opaque type
|
||||
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:18:16
|
||||
@ -41,8 +41,8 @@ LL | fn eq(&self, _other: &(Bar, i32)) -> bool {
|
||||
| expected opaque type, found `b::Bar`
|
||||
| help: change the parameter type to match the trait: `&(b::Foo, i32)`
|
||||
|
|
||||
= note: expected signature `fn(&b::Bar, &(b::Foo, i32)) -> _`
|
||||
found signature `fn(&b::Bar, &(b::Bar, i32)) -> _`
|
||||
= note: expected signature `fn(&b::Bar, &(b::Foo, _)) -> _`
|
||||
found signature `fn(&b::Bar, &(b::Bar, _)) -> _`
|
||||
note: this item must have the opaque type in its signature in order to be able to register hidden types
|
||||
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:24:12
|
||||
|
|
||||
|
@ -6,8 +6,8 @@ LL | real_dispatch(f)
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: expected a closure with arguments `(&mut UIView<'a, T>,)`
|
||||
found a closure with arguments `(&mut UIView<'_, T>,)`
|
||||
= note: expected a closure with arguments `(&mut UIView<'a, _>,)`
|
||||
found a closure with arguments `(&mut UIView<'_, _>,)`
|
||||
note: required by a bound in `real_dispatch`
|
||||
--> $DIR/issue-100690.rs:9:8
|
||||
|
|
||||
|
@ -4,8 +4,8 @@ error[E0308]: mismatched `self` parameter type
|
||||
LL | fn say(self: &Pair<&str, isize>) {
|
||||
| ^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
||||
|
|
||||
= note: expected struct `Pair<&str, _>`
|
||||
found struct `Pair<&str, _>`
|
||||
= note: expected struct `Pair<&_, _>`
|
||||
found struct `Pair<&_, _>`
|
||||
note: the anonymous lifetime defined here...
|
||||
--> $DIR/issue-17905-2.rs:8:24
|
||||
|
|
||||
@ -23,8 +23,8 @@ error[E0308]: mismatched `self` parameter type
|
||||
LL | fn say(self: &Pair<&str, isize>) {
|
||||
| ^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
||||
|
|
||||
= note: expected struct `Pair<&str, _>`
|
||||
found struct `Pair<&str, _>`
|
||||
= note: expected struct `Pair<&_, _>`
|
||||
found struct `Pair<&_, _>`
|
||||
note: the anonymous lifetime as defined here...
|
||||
--> $DIR/issue-17905-2.rs:5:5
|
||||
|
|
||||
|
@ -9,8 +9,8 @@ LL | extern "rust-call" fn call(&self, (_,): (T,)) {}
|
||||
| expected `&'a T`, found type parameter `T`
|
||||
| help: change the parameter type to match the trait: `(&'a T,)`
|
||||
|
|
||||
= note: expected signature `extern "rust-call" fn(&Foo, (&'a T,))`
|
||||
found signature `extern "rust-call" fn(&Foo, (T,))`
|
||||
= note: expected signature `extern "rust-call" fn(&Foo, (&'a _,))`
|
||||
found signature `extern "rust-call" fn(&Foo, (_,))`
|
||||
|
||||
error[E0053]: method `call_mut` has an incompatible type for trait
|
||||
--> $DIR/issue-20225.rs:11:51
|
||||
@ -23,8 +23,8 @@ LL | extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {}
|
||||
| expected `&'a T`, found type parameter `T`
|
||||
| help: change the parameter type to match the trait: `(&'a T,)`
|
||||
|
|
||||
= note: expected signature `extern "rust-call" fn(&mut Foo, (&'a T,))`
|
||||
found signature `extern "rust-call" fn(&mut Foo, (T,))`
|
||||
= note: expected signature `extern "rust-call" fn(&mut Foo, (&'a _,))`
|
||||
found signature `extern "rust-call" fn(&mut Foo, (_,))`
|
||||
|
||||
error[E0053]: method `call_once` has an incompatible type for trait
|
||||
--> $DIR/issue-20225.rs:18:47
|
||||
@ -38,8 +38,8 @@ LL | extern "rust-call" fn call_once(self, (_,): (T,)) {}
|
||||
| expected `&'a T`, found type parameter `T`
|
||||
| help: change the parameter type to match the trait: `(&'a T,)`
|
||||
|
|
||||
= note: expected signature `extern "rust-call" fn(Foo, (&'a T,))`
|
||||
found signature `extern "rust-call" fn(Foo, (T,))`
|
||||
= note: expected signature `extern "rust-call" fn(Foo, (&'a _,))`
|
||||
found signature `extern "rust-call" fn(Foo, (_,))`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -6,8 +6,8 @@ LL | let x: &fn(&B) -> u32 = &B::func;
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&for<'a> fn(&'a B) -> u32`
|
||||
found reference `&for<'a> fn(&'a B) -> u32 {B::func}`
|
||||
= note: expected reference `&for<'a> fn(&'a B) -> _`
|
||||
found reference `&for<'a> fn(&'a B) -> _ {B::func}`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -4,8 +4,8 @@ error[E0308]: method not compatible with trait
|
||||
LL | fn next(&'a mut self) -> Option<Self::Item>
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
||||
|
|
||||
= note: expected signature `fn(&mut RepeatMut<'a, T>) -> Option<_>`
|
||||
found signature `fn(&'a mut RepeatMut<'a, T>) -> Option<_>`
|
||||
= note: expected signature `fn(&mut RepeatMut<'_, _>) -> Option<_>`
|
||||
found signature `fn(&'a mut RepeatMut<'_, _>) -> Option<_>`
|
||||
note: the anonymous lifetime as defined here...
|
||||
--> $DIR/issue-37884.rs:6:5
|
||||
|
|
||||
|
@ -6,8 +6,8 @@ LL | let Some(n): &mut Option<i32> = &&Some(5i32) else { return };
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected mutable reference `&mut Option<i32>`
|
||||
found reference `&&Option<i32>`
|
||||
= note: expected mutable reference `&mut Option<_>`
|
||||
found reference `&&Option<_>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/let-else-binding-explicit-mut-annotated.rs:13:37
|
||||
@ -17,8 +17,8 @@ LL | let Some(n): &mut Option<i32> = &&mut Some(5i32) else { return };
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected mutable reference `&mut Option<i32>`
|
||||
found reference `&&mut Option<i32>`
|
||||
= note: expected mutable reference `&mut Option<_>`
|
||||
found reference `&&mut Option<_>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -54,8 +54,8 @@ error[E0308]: mismatched types
|
||||
LL | take_foo(|a: &i32| a);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected reference `&i32`
|
||||
found reference `&i32`
|
||||
= note: expected reference `&_`
|
||||
found reference `&_`
|
||||
note: the lifetime requirement is introduced here
|
||||
--> $DIR/issue-79187-2.rs:5:21
|
||||
|
|
||||
@ -68,8 +68,8 @@ error[E0308]: mismatched types
|
||||
LL | take_foo(|a: &i32| -> &i32 { a });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected reference `&i32`
|
||||
found reference `&i32`
|
||||
= note: expected reference `&_`
|
||||
found reference `&_`
|
||||
note: the lifetime requirement is introduced here
|
||||
--> $DIR/issue-79187-2.rs:5:21
|
||||
|
|
||||
|
@ -12,8 +12,8 @@ LL | |
|
||||
LL | | };
|
||||
| |_____- `match` arms have incompatible types
|
||||
|
|
||||
= note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
|
||||
found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
|
||||
= note: expected fn pointer `for<'a, 'b> fn(&'a _, &'b _) -> &'a _`
|
||||
found fn pointer `for<'a> fn(&'a _, &'a _) -> &'a _`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -4,8 +4,8 @@ error[E0308]: mismatched types
|
||||
LL | _ => y,
|
||||
| ^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
|
||||
found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
|
||||
= note: expected fn pointer `for<'a, 'b> fn(&'a _, &'b _) -> &'a _`
|
||||
found fn pointer `for<'a> fn(&'a _, &'a _) -> &'a _`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -11,8 +11,8 @@ LL | |
|
||||
LL | | };
|
||||
| |_____- `match` arms have incompatible types
|
||||
|
|
||||
= note: expected fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
|
||||
found fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
|
||||
= note: expected fn pointer `for<'a> fn(&'a _, &'a _) -> &'a _`
|
||||
found fn pointer `for<'a, 'b> fn(&'a _, &'b _) -> &'a _`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -4,8 +4,8 @@ error[E0308]: mismatched types
|
||||
LL | let Foo(ref mut y): Foo<fn(&'static str)> = x;
|
||||
| ^^^^^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'a> fn(&'a str)`
|
||||
found fn pointer `fn(&str)`
|
||||
= note: expected fn pointer `for<'a> fn(&'a _)`
|
||||
found fn pointer `fn(&_)`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -6,8 +6,8 @@ LL | a.iter().map(|_: (u32, u32)| 45);
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected closure signature `fn(&(u32, u32)) -> _`
|
||||
found closure signature `fn((u32, u32)) -> _`
|
||||
= note: expected closure signature `fn(&(_, _)) -> _`
|
||||
found closure signature `fn((_, _)) -> _`
|
||||
note: required by a bound in `map`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
help: consider adjusting the signature so it borrows its argument
|
||||
|
@ -6,8 +6,8 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count();
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected closure signature `for<'a> fn(&'a &str) -> _`
|
||||
found closure signature `for<'a> fn(&'a str) -> _`
|
||||
= note: expected closure signature `for<'a> fn(&'a &_) -> _`
|
||||
found closure signature `for<'a> fn(&'a _) -> _`
|
||||
note: required by a bound in `filter`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
help: consider adjusting the signature so it borrows its argument
|
||||
|
@ -6,8 +6,8 @@ LL | needs_i32_ref_fn(foo::<()>);
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected fn pointer `fn(&'static i32, i32)`
|
||||
found fn item `fn(i32, &'static i32) {foo::<()>}`
|
||||
= note: expected fn pointer `fn(&'static _, _)`
|
||||
found fn item `fn(_, &'static _) {foo::<()>}`
|
||||
note: function defined here
|
||||
--> $DIR/normalize-fn-sig.rs:11:4
|
||||
|
|
||||
|
@ -6,8 +6,8 @@ LL | let mut x: HashSet<Day> = v.clone();
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected struct `HashSet<Day>`
|
||||
found reference `&HashSet<Day>`
|
||||
= note: expected struct `HashSet<_>`
|
||||
found reference `&HashSet<_>`
|
||||
note: `HashSet<Day>` does not implement `Clone`, so `&HashSet<Day>` was cloned instead
|
||||
--> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:18:39
|
||||
|
|
||||
|
@ -4,8 +4,8 @@ error[E0308]: mismatched types
|
||||
LL | let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
|
||||
| ^^^^^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32`
|
||||
found fn pointer `for<'a> fn(&'a u32, &'a u32) -> &'a u32`
|
||||
= note: expected fn pointer `for<'a, 'b> fn(&'a _, &'b _) -> &'a _`
|
||||
found fn pointer `for<'a> fn(&'a _, &'a _) -> &'a _`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/hr-fn-aaa-as-aba.rs:20:12
|
||||
@ -13,8 +13,8 @@ error[E0308]: mismatched types
|
||||
LL | let _: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32`
|
||||
found fn pointer `for<'a> fn(&'a u32, &'a u32) -> &'a u32`
|
||||
= note: expected fn pointer `for<'a, 'b> fn(&'a _, &'b _) -> &'a _`
|
||||
found fn pointer `for<'a> fn(&'a _, &'a _) -> &'a _`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -4,8 +4,8 @@ error[E0308]: mismatched types
|
||||
LL | let b: fn(&u32) -> &u32 = a;
|
||||
| ^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'a> fn(&'a u32) -> &'a u32`
|
||||
found fn pointer `fn(&u32) -> &u32`
|
||||
= note: expected fn pointer `for<'a> fn(&'a _) -> &'a _`
|
||||
found fn pointer `fn(&_) -> &_`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -4,8 +4,8 @@ error[E0308]: const not compatible with trait
|
||||
LL | const AC: Option<&'c str> = None;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
||||
|
|
||||
= note: expected enum `Option<&'b str>`
|
||||
found enum `Option<&'c str>`
|
||||
= note: expected enum `Option<&'b _>`
|
||||
found enum `Option<&'c _>`
|
||||
note: the lifetime `'c` as defined here...
|
||||
--> $DIR/trait-associated-constant.rs:20:18
|
||||
|
|
||||
|
@ -57,8 +57,8 @@ LL | let (Ok(ref a) | Err(ref mut a)): Result<&u8, &mut u8> = Ok(&0);
|
||||
| | types differ in mutability
|
||||
| first introduced with type `&&u8` here
|
||||
|
|
||||
= note: expected reference `&&u8`
|
||||
found mutable reference `&mut &mut u8`
|
||||
= note: expected reference `&&_`
|
||||
found mutable reference `&mut &mut _`
|
||||
= note: a binding must have the same type in all alternatives
|
||||
|
||||
error[E0308]: mismatched types
|
||||
|
35
tests/ui/privacy/auxiliary/issue-117997.rs
Normal file
35
tests/ui/privacy/auxiliary/issue-117997.rs
Normal file
@ -0,0 +1,35 @@
|
||||
// no-prefer-dynamic
|
||||
// compile-flags: --crate-type=rlib
|
||||
|
||||
pub use impl_mod::TraitImplementer as Implementer;
|
||||
|
||||
pub use trait_mod::get_assoc;
|
||||
|
||||
mod impl_mod {
|
||||
use crate::trait_mod::TraitWithAssocType;
|
||||
|
||||
pub struct TraitImplementer {}
|
||||
pub struct AssociatedType {}
|
||||
|
||||
impl AssociatedType {
|
||||
pub fn method_on_assoc(&self) -> i32 {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl TraitWithAssocType for TraitImplementer {
|
||||
type AssocType = AssociatedType;
|
||||
}
|
||||
}
|
||||
|
||||
mod trait_mod {
|
||||
use crate::Implementer;
|
||||
|
||||
pub fn get_assoc() -> <Implementer as TraitWithAssocType>::AssocType {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub trait TraitWithAssocType {
|
||||
type AssocType;
|
||||
}
|
||||
}
|
8
tests/ui/privacy/issue-117997.rs
Normal file
8
tests/ui/privacy/issue-117997.rs
Normal file
@ -0,0 +1,8 @@
|
||||
// aux-build:issue-117997.rs
|
||||
// build-pass
|
||||
|
||||
extern crate issue_117997;
|
||||
|
||||
pub fn main() {
|
||||
issue_117997::get_assoc().method_on_assoc();
|
||||
}
|
@ -106,6 +106,7 @@ mod aliases_pub {
|
||||
pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
|
||||
//~^ WARNING type `aliases_pub::Priv` is more private than the item `aliases_pub::f3`
|
||||
//~| WARNING associated type `aliases_pub::PrivTr::Assoc` is more private than the item `aliases_pub::f3`
|
||||
//~^^^ WARNING trait `aliases_pub::PrivTr` is more private than the item `aliases_pub::f3`
|
||||
|
||||
impl PrivUseAlias {
|
||||
pub fn f(arg: Priv) {}
|
||||
@ -135,6 +136,7 @@ mod aliases_priv {
|
||||
pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
|
||||
//~^ WARNING type `aliases_priv::Priv` is more private than the item `aliases_priv::f3`
|
||||
//~| WARNING associated type `aliases_priv::PrivTr::Assoc` is more private than the item `aliases_priv::f3`
|
||||
//~^^^ WARNING trait `aliases_priv::PrivTr` is more private than the item `aliases_priv::f3`
|
||||
}
|
||||
|
||||
mod aliases_params {
|
||||
|
@ -288,6 +288,18 @@ note: but associated type `aliases_pub::PrivTr::Assoc` is only usable at visibil
|
||||
LL | type Assoc = m::Pub3;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
warning: trait `aliases_pub::PrivTr` is more private than the item `aliases_pub::f3`
|
||||
--> $DIR/private-in-public.rs:106:5
|
||||
|
|
||||
LL | pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_pub::f3` is reachable at visibility `pub(crate)`
|
||||
|
|
||||
note: but trait `aliases_pub::PrivTr` is only usable at visibility `pub(self)`
|
||||
--> $DIR/private-in-public.rs:100:5
|
||||
|
|
||||
LL | trait PrivTr {
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
warning: type `aliases_pub::Priv` is more private than the item `aliases_pub::f3`
|
||||
--> $DIR/private-in-public.rs:106:5
|
||||
|
|
||||
@ -301,76 +313,88 @@ LL | struct Priv;
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
warning: type `Priv1` is more private than the item `aliases_priv::f1`
|
||||
--> $DIR/private-in-public.rs:133:5
|
||||
--> $DIR/private-in-public.rs:134:5
|
||||
|
|
||||
LL | pub fn f1(arg: PrivUseAlias) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_priv::f1` is reachable at visibility `pub(crate)`
|
||||
|
|
||||
note: but type `Priv1` is only usable at visibility `pub(self)`
|
||||
--> $DIR/private-in-public.rs:118:5
|
||||
--> $DIR/private-in-public.rs:119:5
|
||||
|
|
||||
LL | struct Priv1;
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
warning: type `Priv2` is more private than the item `aliases_priv::f2`
|
||||
--> $DIR/private-in-public.rs:134:5
|
||||
--> $DIR/private-in-public.rs:135:5
|
||||
|
|
||||
LL | pub fn f2(arg: PrivAlias) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_priv::f2` is reachable at visibility `pub(crate)`
|
||||
|
|
||||
note: but type `Priv2` is only usable at visibility `pub(self)`
|
||||
--> $DIR/private-in-public.rs:119:5
|
||||
--> $DIR/private-in-public.rs:120:5
|
||||
|
|
||||
LL | struct Priv2;
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
warning: associated type `aliases_priv::PrivTr::Assoc` is more private than the item `aliases_priv::f3`
|
||||
--> $DIR/private-in-public.rs:135:5
|
||||
--> $DIR/private-in-public.rs:136:5
|
||||
|
|
||||
LL | pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_priv::f3` is reachable at visibility `pub(crate)`
|
||||
|
|
||||
note: but associated type `aliases_priv::PrivTr::Assoc` is only usable at visibility `pub(self)`
|
||||
--> $DIR/private-in-public.rs:129:9
|
||||
--> $DIR/private-in-public.rs:130:9
|
||||
|
|
||||
LL | type Assoc = Priv3;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
warning: trait `aliases_priv::PrivTr` is more private than the item `aliases_priv::f3`
|
||||
--> $DIR/private-in-public.rs:136:5
|
||||
|
|
||||
LL | pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_priv::f3` is reachable at visibility `pub(crate)`
|
||||
|
|
||||
note: but trait `aliases_priv::PrivTr` is only usable at visibility `pub(self)`
|
||||
--> $DIR/private-in-public.rs:129:5
|
||||
|
|
||||
LL | trait PrivTr {
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
warning: type `aliases_priv::Priv` is more private than the item `aliases_priv::f3`
|
||||
--> $DIR/private-in-public.rs:135:5
|
||||
--> $DIR/private-in-public.rs:136:5
|
||||
|
|
||||
LL | pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_priv::f3` is reachable at visibility `pub(crate)`
|
||||
|
|
||||
note: but type `aliases_priv::Priv` is only usable at visibility `pub(self)`
|
||||
--> $DIR/private-in-public.rs:116:5
|
||||
--> $DIR/private-in-public.rs:117:5
|
||||
|
|
||||
LL | struct Priv;
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
warning: type `aliases_params::Priv` is more private than the item `aliases_params::f2`
|
||||
--> $DIR/private-in-public.rs:145:5
|
||||
--> $DIR/private-in-public.rs:147:5
|
||||
|
|
||||
LL | pub fn f2(arg: PrivAliasGeneric) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_params::f2` is reachable at visibility `pub(crate)`
|
||||
|
|
||||
note: but type `aliases_params::Priv` is only usable at visibility `pub(self)`
|
||||
--> $DIR/private-in-public.rs:141:5
|
||||
--> $DIR/private-in-public.rs:143:5
|
||||
|
|
||||
LL | struct Priv;
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
warning: type `aliases_params::Priv` is more private than the item `aliases_params::f3`
|
||||
--> $DIR/private-in-public.rs:147:5
|
||||
--> $DIR/private-in-public.rs:149:5
|
||||
|
|
||||
LL | pub fn f3(arg: Result<u8>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_params::f3` is reachable at visibility `pub(crate)`
|
||||
|
|
||||
note: but type `aliases_params::Priv` is only usable at visibility `pub(self)`
|
||||
--> $DIR/private-in-public.rs:141:5
|
||||
--> $DIR/private-in-public.rs:143:5
|
||||
|
|
||||
LL | struct Priv;
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
warning: 31 warnings emitted
|
||||
warning: 33 warnings emitted
|
||||
|
||||
|
@ -6,8 +6,8 @@ LL | demo(tell(1)..tell(10));
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected reference `&std::ops::Range<usize>`
|
||||
found struct `std::ops::Range<usize>`
|
||||
= note: expected reference `&std::ops::Range<_>`
|
||||
found struct `std::ops::Range<_>`
|
||||
note: function defined here
|
||||
--> $DIR/issue-73553-misinterp-range-literal.rs:3:4
|
||||
|
|
||||
|
@ -6,8 +6,8 @@ LL | fn f<'r>(f: fn(Cell<(&'r i32, &i32)>)) -> Ty {
|
||||
LL | f
|
||||
| ^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'r> fn(Cell<(&'r i32, &'r i32)>)`
|
||||
found fn pointer `for<'a> fn(Cell<(&'r i32, &'a i32)>)`
|
||||
= note: expected fn pointer `for<'r> fn(Cell<(&'r _, &'r _)>)`
|
||||
found fn pointer `for<'a> fn(Cell<(&'r _, &'a _)>)`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -6,8 +6,8 @@ LL | let _: fn(&mut &isize, &mut &isize) = a;
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)`
|
||||
found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}`
|
||||
= note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)`
|
||||
found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -6,8 +6,8 @@ LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b isize, &'c mut &'d isize, &'e mut &'f isize)`
|
||||
found fn item `for<'a, 'b, 'c> fn(&'a mut &isize, &'b mut &isize, &'c mut &isize) {a::<'_, '_, '_>}`
|
||||
= note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b _, &'c mut &'d _, &'e mut &'f _)`
|
||||
found fn item `for<'a, 'b, 'c> fn(&'a mut &_, &'b mut &_, &'c mut &_) {a::<'_, '_, '_>}`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -6,8 +6,8 @@ LL | let _: fn(&mut &isize, &mut &isize) = a;
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)`
|
||||
found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}`
|
||||
= note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)`
|
||||
found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -62,8 +62,8 @@ LL | Opts::A(ref mut i) | Opts::B(ref i) => {}
|
||||
| |
|
||||
| first introduced with type `&mut isize` here
|
||||
|
|
||||
= note: expected mutable reference `&mut isize`
|
||||
found reference `&isize`
|
||||
= note: expected mutable reference `&mut _`
|
||||
found reference `&_`
|
||||
= note: in the same arm, a binding must have the same type in all alternatives
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
@ -6,8 +6,8 @@ LL | match &s {
|
||||
LL | "abc" => true,
|
||||
| ^^^^^ expected `&&str`, found `&str`
|
||||
|
|
||||
= note: expected reference `&&str`
|
||||
found reference `&'static str`
|
||||
= note: expected reference `&&_`
|
||||
found reference `&'static _`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/lit.rs:16:9
|
||||
|
@ -4,8 +4,8 @@ error[E0308]: mismatched types
|
||||
LL | fn y(&self, y: f64) -> Self { P{y, .. self.clone() } }
|
||||
| ^^^^^^^^^^^^ expected `P<T>`, found `&P<T>`
|
||||
|
|
||||
= note: expected struct `P<T>`
|
||||
found reference `&P<T>`
|
||||
= note: expected struct `P<_>`
|
||||
found reference `&P<_>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -4,8 +4,8 @@ error[E0308]: mismatched types
|
||||
LL | func: &foo,
|
||||
| ^^^^ expected `&fn() -> Option<isize>`, found `&fn() -> Option<isize> {foo}`
|
||||
|
|
||||
= note: expected reference `&fn() -> Option<isize>`
|
||||
found reference `&fn() -> Option<isize> {foo}`
|
||||
= note: expected reference `&fn() -> Option<_>`
|
||||
found reference `&fn() -> Option<_> {foo}`
|
||||
= note: fn items are distinct from fn pointers
|
||||
help: consider casting to a fn pointer
|
||||
|
|
||||
|
@ -78,8 +78,8 @@ LL | let y: Option<&usize> = x;
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected enum `Option<&usize>`
|
||||
found reference `&Option<usize>`
|
||||
= note: expected enum `Option<&_>`
|
||||
found reference `&Option<_>`
|
||||
help: try using `.as_ref()` to convert `&Option<usize>` to `Option<&usize>`
|
||||
|
|
||||
LL | let y: Option<&usize> = x.as_ref();
|
||||
@ -93,8 +93,8 @@ LL | let y: Result<&usize, &usize> = x;
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected enum `Result<&usize, &usize>`
|
||||
found reference `&Result<usize, usize>`
|
||||
= note: expected enum `Result<&_, &_>`
|
||||
found reference `&Result<_, _>`
|
||||
help: try using `.as_ref()` to convert `&Result<usize, usize>` to `Result<&usize, &usize>`
|
||||
|
|
||||
LL | let y: Result<&usize, &usize> = x.as_ref();
|
||||
@ -108,8 +108,8 @@ LL | let y: Result<&usize, usize> = x;
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected enum `Result<&usize, usize>`
|
||||
found reference `&Result<usize, usize>`
|
||||
= note: expected enum `Result<&_, _>`
|
||||
found reference `&Result<_, _>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/as-ref.rs:22:42
|
||||
|
@ -8,8 +8,8 @@ LL | fn wat<T>(t: &T) -> T {
|
||||
LL | t.clone()
|
||||
| ^^^^^^^^^ expected type parameter `T`, found `&T`
|
||||
|
|
||||
= note: expected type parameter `T`
|
||||
found reference `&T`
|
||||
= note: expected type parameter `_`
|
||||
found reference `&_`
|
||||
note: `T` does not implement `Clone`, so `&T` was cloned instead
|
||||
--> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5
|
||||
|
|
||||
|
@ -18,8 +18,8 @@ LL | fn method(&self) -> Option<&Vec<u8>> {
|
||||
LL | self.option..as_ref().map(|x| x)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Option<&Vec<u8>>`, found `Range<Option<Vec<u8>>>`
|
||||
|
|
||||
= note: expected enum `Option<&Vec<u8>>`
|
||||
found struct `std::ops::Range<Option<Vec<u8>>>`
|
||||
= note: expected enum `Option<&Vec<_>>`
|
||||
found struct `std::ops::Range<Option<Vec<_>>>`
|
||||
help: you likely meant to write a method call instead of a range
|
||||
|
|
||||
LL - self.option..as_ref().map(|x| x)
|
||||
|
@ -32,8 +32,8 @@ LL | fn suggestion2(opt: &mut Option<String>) {
|
||||
LL | opt = Some(String::new())
|
||||
| ^^^^^^^^^^^^^^^^^^^ expected `&mut Option<String>`, found `Option<String>`
|
||||
|
|
||||
= note: expected mutable reference `&mut Option<String>`
|
||||
found enum `Option<String>`
|
||||
= note: expected mutable reference `&mut Option<_>`
|
||||
found enum `Option<_>`
|
||||
help: consider dereferencing here to assign to the mutably borrowed value
|
||||
|
|
||||
LL | *opt = Some(String::new())
|
||||
|
@ -0,0 +1,16 @@
|
||||
// run-rustfix
|
||||
|
||||
struct A {}
|
||||
|
||||
impl A {
|
||||
fn hello(_a: i32) {}
|
||||
fn test(_a: Self, _b: i32) {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _a = A {};
|
||||
A::hello(1);
|
||||
//~^ ERROR no method named `hello` found
|
||||
A::test(_a, 1);
|
||||
//~^ ERROR no method named `test` found
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
// run-rustfix
|
||||
|
||||
struct A {}
|
||||
|
||||
impl A {
|
||||
fn hello(_a: i32) {}
|
||||
fn test(_a: Self, _b: i32) {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _a = A {};
|
||||
_a.hello(1);
|
||||
//~^ ERROR no method named `hello` found
|
||||
_a.test(1);
|
||||
//~^ ERROR no method named `test` found
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
error[E0599]: no method named `hello` found for struct `A` in the current scope
|
||||
--> $DIR/suggest-assoc-fn-call-without-receiver.rs:12:8
|
||||
|
|
||||
LL | struct A {}
|
||||
| -------- method `hello` not found for this struct
|
||||
...
|
||||
LL | _a.hello(1);
|
||||
| ---^^^^^---
|
||||
| | |
|
||||
| | this is an associated function, not a method
|
||||
| help: use associated function syntax instead: `A::hello(1)`
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in an impl for the type `A`
|
||||
--> $DIR/suggest-assoc-fn-call-without-receiver.rs:6:5
|
||||
|
|
||||
LL | fn hello(_a: i32) {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0599]: no method named `test` found for struct `A` in the current scope
|
||||
--> $DIR/suggest-assoc-fn-call-without-receiver.rs:14:8
|
||||
|
|
||||
LL | struct A {}
|
||||
| -------- method `test` not found for this struct
|
||||
...
|
||||
LL | _a.test(1);
|
||||
| ---^^^^---
|
||||
| | |
|
||||
| | this is an associated function, not a method
|
||||
| help: use associated function syntax instead: `A::test(_a, 1)`
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: the candidate is defined in an impl for the type `A`
|
||||
--> $DIR/suggest-assoc-fn-call-without-receiver.rs:7:5
|
||||
|
|
||||
LL | fn test(_a: Self, _b: i32) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
@ -9,8 +9,8 @@ note: type in trait
|
||||
|
|
||||
LL | fn jumbo(&self, x: &usize) -> usize;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: expected signature `fn(&usize, &usize) -> usize`
|
||||
found signature `unsafe fn(&usize, &usize)`
|
||||
= note: expected signature `fn(&_, &_) -> usize`
|
||||
found signature `unsafe fn(&_, &_)`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -7,8 +7,8 @@ LL | fn mul(self, s: &f64) -> Vec1 {
|
||||
| expected `f64`, found `&f64`
|
||||
| help: change the parameter type to match the trait: `f64`
|
||||
|
|
||||
= note: expected signature `fn(Vec1, f64) -> Vec1`
|
||||
found signature `fn(Vec1, &f64) -> Vec1`
|
||||
= note: expected signature `fn(Vec1, _) -> Vec1`
|
||||
found signature `fn(Vec1, &_) -> Vec1`
|
||||
|
||||
error[E0053]: method `mul` has an incompatible type for trait
|
||||
--> $DIR/wrong-mul-method-signature.rs:33:21
|
||||
|
@ -25,8 +25,8 @@ LL | bar(v);
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected struct `Vec<i32>`
|
||||
found struct `Vec<&i32>`
|
||||
= note: expected struct `Vec<_>`
|
||||
found struct `Vec<&_>`
|
||||
note: function defined here
|
||||
--> $DIR/point-at-inference-2.rs:1:4
|
||||
|
|
||||
@ -43,8 +43,8 @@ LL | bar(v);
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected struct `Vec<i32>`
|
||||
found struct `Vec<&i32>`
|
||||
= note: expected struct `Vec<_>`
|
||||
found struct `Vec<&_>`
|
||||
note: function defined here
|
||||
--> $DIR/point-at-inference-2.rs:1:4
|
||||
|
|
||||
|
@ -382,8 +382,8 @@ LL | want::<&Foo<foo>>(f);
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected reference `&Foo<foo>`
|
||||
found struct `Foo<foo>`
|
||||
= note: expected reference `&Foo<_>`
|
||||
found struct `Foo<_>`
|
||||
note: function defined here
|
||||
--> $DIR/type-mismatch.rs:14:4
|
||||
|
|
||||
@ -402,8 +402,8 @@ LL | want::<&Foo<foo, B>>(f);
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected reference `&Foo<foo, B>`
|
||||
found struct `Foo<foo>`
|
||||
= note: expected reference `&Foo<_, B>`
|
||||
found struct `Foo<_, A>`
|
||||
note: function defined here
|
||||
--> $DIR/type-mismatch.rs:14:4
|
||||
|
|
||||
@ -546,8 +546,8 @@ LL | want::<&Foo<foo>>(f);
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected reference `&Foo<foo>`
|
||||
found struct `Foo<foo, B>`
|
||||
= note: expected reference `&Foo<_, A>`
|
||||
found struct `Foo<_, B>`
|
||||
note: function defined here
|
||||
--> $DIR/type-mismatch.rs:14:4
|
||||
|
|
||||
@ -562,8 +562,8 @@ LL | want::<&Foo<foo, B>>(f);
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected reference `&Foo<foo, B>`
|
||||
found struct `Foo<foo, B>`
|
||||
= note: expected reference `&Foo<_, _>`
|
||||
found struct `Foo<_, _>`
|
||||
note: function defined here
|
||||
--> $DIR/type-mismatch.rs:14:4
|
||||
|
|
||||
@ -726,8 +726,8 @@ LL | want::<&Foo<foo>>(f);
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected reference `&Foo<foo>`
|
||||
found struct `Foo<foo, B, A>`
|
||||
= note: expected reference `&Foo<_, A, B>`
|
||||
found struct `Foo<_, B, A>`
|
||||
note: function defined here
|
||||
--> $DIR/type-mismatch.rs:14:4
|
||||
|
|
||||
@ -742,8 +742,8 @@ LL | want::<&Foo<foo, B>>(f);
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected reference `&Foo<foo, B>`
|
||||
found struct `Foo<foo, B, A>`
|
||||
= note: expected reference `&Foo<_, _, B>`
|
||||
found struct `Foo<_, _, A>`
|
||||
note: function defined here
|
||||
--> $DIR/type-mismatch.rs:14:4
|
||||
|
|
||||
|
@ -44,8 +44,8 @@ LL | fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V {
|
||||
LL | map[k]
|
||||
| ^ expected `&K`, found type parameter `K`
|
||||
|
|
||||
= note: expected reference `&K`
|
||||
found type parameter `K`
|
||||
= note: expected reference `&_`
|
||||
found type parameter `_`
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | map[&k]
|
||||
@ -59,8 +59,8 @@ LL | fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V {
|
||||
LL | map[k]
|
||||
| ^^^^^^ expected `&V`, found type parameter `V`
|
||||
|
|
||||
= note: expected reference `&'a V`
|
||||
found type parameter `V`
|
||||
= note: expected reference `&'a _`
|
||||
found type parameter `_`
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | &map[k]
|
||||
|
@ -12,8 +12,8 @@ note: type in trait
|
||||
|
|
||||
LL | fn values(&self) -> Self::Values;
|
||||
| ^^^^^
|
||||
= note: expected signature `fn(&Option<T>)`
|
||||
found signature `fn(Option<T>)`
|
||||
= note: expected signature `fn(&Option<_>)`
|
||||
found signature `fn(Option<_>)`
|
||||
|
||||
error[E0631]: type mismatch in function arguments
|
||||
--> $DIR/mismatched-map-under-self.rs:12:18
|
||||
|
@ -39,12 +39,12 @@ impl<'a, T> SomeTrait for &'a Bar<T> {
|
||||
//~| ERROR has an incompatible type for trait
|
||||
fn dummy3(self: &&Bar<T>) {}
|
||||
//~^ ERROR mismatched `self` parameter type
|
||||
//~| expected reference `&'a Bar<T>`
|
||||
//~| found reference `&Bar<T>`
|
||||
//~| expected reference `&'a Bar<_>`
|
||||
//~| found reference `&Bar<_>`
|
||||
//~| lifetime mismatch
|
||||
//~| ERROR mismatched `self` parameter type
|
||||
//~| expected reference `&'a Bar<T>`
|
||||
//~| found reference `&Bar<T>`
|
||||
//~| expected reference `&'a Bar<_>`
|
||||
//~| found reference `&Bar<_>`
|
||||
//~| lifetime mismatch
|
||||
}
|
||||
|
||||
|
@ -31,8 +31,8 @@ error[E0308]: mismatched `self` parameter type
|
||||
LL | fn dummy2(self: &Bar<T>) {}
|
||||
| ^^^^^^^ lifetime mismatch
|
||||
|
|
||||
= note: expected reference `&'a Bar<T>`
|
||||
found reference `&Bar<T>`
|
||||
= note: expected reference `&'a Bar<_>`
|
||||
found reference `&Bar<_>`
|
||||
note: the anonymous lifetime defined here...
|
||||
--> $DIR/ufcs-explicit-self-bad.rs:37:21
|
||||
|
|
||||
@ -50,8 +50,8 @@ error[E0308]: mismatched `self` parameter type
|
||||
LL | fn dummy2(self: &Bar<T>) {}
|
||||
| ^^^^^^^ lifetime mismatch
|
||||
|
|
||||
= note: expected reference `&'a Bar<T>`
|
||||
found reference `&Bar<T>`
|
||||
= note: expected reference `&'a Bar<_>`
|
||||
found reference `&Bar<_>`
|
||||
note: the lifetime `'a` as defined here...
|
||||
--> $DIR/ufcs-explicit-self-bad.rs:35:6
|
||||
|
|
||||
@ -69,8 +69,8 @@ error[E0308]: mismatched `self` parameter type
|
||||
LL | fn dummy3(self: &&Bar<T>) {}
|
||||
| ^^^^^^^^ lifetime mismatch
|
||||
|
|
||||
= note: expected reference `&'a Bar<T>`
|
||||
found reference `&Bar<T>`
|
||||
= note: expected reference `&'a Bar<_>`
|
||||
found reference `&Bar<_>`
|
||||
note: the anonymous lifetime defined here...
|
||||
--> $DIR/ufcs-explicit-self-bad.rs:40:22
|
||||
|
|
||||
@ -88,8 +88,8 @@ error[E0308]: mismatched `self` parameter type
|
||||
LL | fn dummy3(self: &&Bar<T>) {}
|
||||
| ^^^^^^^^ lifetime mismatch
|
||||
|
|
||||
= note: expected reference `&'a Bar<T>`
|
||||
found reference `&Bar<T>`
|
||||
= note: expected reference `&'a Bar<_>`
|
||||
found reference `&Bar<_>`
|
||||
note: the lifetime `'a` as defined here...
|
||||
--> $DIR/ufcs-explicit-self-bad.rs:35:6
|
||||
|
|
||||
@ -115,8 +115,8 @@ note: type in trait
|
||||
|
|
||||
LL | fn dummy2(&self);
|
||||
| ^^^^^
|
||||
= note: expected signature `fn(&&'a Bar<T>)`
|
||||
found signature `fn(&Bar<T>)`
|
||||
= note: expected signature `fn(&&'a Bar<_>)`
|
||||
found signature `fn(&Bar<_>)`
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user